brighterscript 0.66.0-alpha.1 → 0.66.0-alpha.10
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 +215 -10
- package/README.md +13 -3
- package/bsconfig.schema.json +15 -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 +150 -0
- package/dist/AstValidationSegmenter.js.map +1 -0
- package/dist/BsConfig.d.ts +13 -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 +0 -1
- package/dist/CodeActionUtil.d.ts +2 -2
- package/dist/CommentFlagProcessor.d.ts +4 -3
- package/dist/CommentFlagProcessor.js.map +1 -1
- package/dist/DiagnosticCollection.js +8 -5
- package/dist/DiagnosticCollection.js.map +1 -1
- package/dist/DiagnosticMessages.d.ts +34 -4
- package/dist/DiagnosticMessages.js +59 -4
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/FunctionScope.d.ts +1 -1
- package/dist/LanguageServer.d.ts +23 -1
- package/dist/LanguageServer.js +139 -57
- package/dist/LanguageServer.js.map +1 -1
- package/dist/Logger.d.ts +3 -2
- package/dist/Logger.js +10 -2
- package/dist/Logger.js.map +1 -1
- package/dist/PluginInterface.d.ts +11 -2
- package/dist/PluginInterface.js +69 -10
- package/dist/PluginInterface.js.map +1 -1
- package/dist/Program.d.ts +138 -49
- package/dist/Program.js +637 -349
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.d.ts +10 -4
- package/dist/ProgramBuilder.js +76 -74
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +52 -49
- package/dist/Scope.js +298 -274
- package/dist/Scope.js.map +1 -1
- package/dist/SymbolTable.d.ts +35 -14
- package/dist/SymbolTable.js +90 -29
- 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/XmlScope.d.ts +7 -4
- package/dist/XmlScope.js +52 -12
- package/dist/XmlScope.js.map +1 -1
- package/dist/astUtils/{AstEditor.d.ts → Editor.d.ts} +6 -1
- package/dist/astUtils/{AstEditor.js → Editor.js} +9 -3
- package/dist/astUtils/Editor.js.map +1 -0
- package/dist/astUtils/{AstEditor.spec.js → Editor.spec.js} +10 -6
- package/dist/astUtils/Editor.spec.js.map +1 -0
- package/dist/astUtils/creators.d.ts +3 -1
- package/dist/astUtils/creators.js +14 -4
- package/dist/astUtils/creators.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +37 -9
- package/dist/astUtils/reflection.js +83 -14
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/reflection.spec.js +87 -5
- package/dist/astUtils/reflection.spec.js.map +1 -1
- package/dist/astUtils/visitors.d.ts +14 -3
- package/dist/astUtils/visitors.js +22 -2
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/astUtils/visitors.spec.js +58 -7
- package/dist/astUtils/visitors.spec.js.map +1 -1
- package/dist/bscPlugin/BscPlugin.d.ts +10 -2
- package/dist/bscPlugin/BscPlugin.js +24 -4
- package/dist/bscPlugin/BscPlugin.js.map +1 -1
- package/dist/bscPlugin/CallExpressionInfo.d.ts +3 -3
- package/dist/bscPlugin/CallExpressionInfo.js.map +1 -1
- 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/codeActions/CodeActionsProcessor.js +8 -8
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +4 -4
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +50 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.js +442 -23
- package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +1737 -0
- package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/fileProviders/FileProvider.d.ts +9 -0
- package/dist/bscPlugin/fileProviders/FileProvider.js +51 -0
- package/dist/bscPlugin/fileProviders/FileProvider.js.map +1 -0
- package/dist/bscPlugin/hover/HoverProcessor.d.ts +7 -3
- package/dist/bscPlugin/hover/HoverProcessor.js +133 -103
- package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -1
- package/dist/bscPlugin/hover/HoverProcessor.spec.js +241 -29
- package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +1 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +43 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +22 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/serialize/BslibInjector.spec.js +19 -0
- package/dist/bscPlugin/serialize/BslibInjector.spec.js.map +1 -0
- package/dist/bscPlugin/serialize/BslibManager.d.ts +9 -0
- package/dist/bscPlugin/serialize/BslibManager.js +40 -0
- package/dist/bscPlugin/serialize/BslibManager.js.map +1 -0
- package/dist/bscPlugin/serialize/FileSerializer.d.ts +9 -0
- package/dist/bscPlugin/serialize/FileSerializer.js +72 -0
- package/dist/bscPlugin/serialize/FileSerializer.js.map +1 -0
- package/dist/bscPlugin/transpile/{BrsFilePreTranspileProcessor.d.ts → BrsFileTranspileProcessor.d.ts} +4 -2
- package/dist/bscPlugin/transpile/{BrsFilePreTranspileProcessor.js → BrsFileTranspileProcessor.js} +29 -5
- 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 +2 -2
- package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js.map +1 -1
- package/dist/bscPlugin/validation/BrsFileValidator.d.ts +0 -4
- package/dist/bscPlugin/validation/BrsFileValidator.js +34 -29
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js +1 -1
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -1
- package/dist/bscPlugin/validation/ScopeValidator.d.ts +28 -7
- package/dist/bscPlugin/validation/ScopeValidator.js +393 -205
- 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 +2038 -0
- package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -0
- package/dist/bscPlugin/validation/XmlFileValidator.js +2 -2
- package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -1
- package/dist/cli.js +104 -13
- package/dist/cli.js.map +1 -1
- package/dist/deferred.d.ts +3 -3
- package/dist/deferred.js.map +1 -1
- package/dist/diagnosticUtils.d.ts +8 -2
- package/dist/diagnosticUtils.js +45 -16
- package/dist/diagnosticUtils.js.map +1 -1
- package/dist/examples/plugins/removePrint.js +1 -1
- 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 +383 -56
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +73 -46
- package/dist/files/BrsFile.js +370 -534
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +1139 -682
- package/dist/files/BrsFile.spec.js.map +1 -1
- 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/File.d.ts +106 -0
- package/dist/files/File.js +16 -0
- package/dist/files/File.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 +56 -23
- package/dist/files/XmlFile.js +88 -60
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/XmlFile.spec.js +64 -93
- package/dist/files/XmlFile.spec.js.map +1 -1
- package/dist/files/tests/imports.spec.js +21 -8
- package/dist/files/tests/imports.spec.js.map +1 -1
- package/dist/files/tests/optionalChaning.spec.js +14 -14
- package/dist/files/tests/optionalChaning.spec.js.map +1 -1
- package/dist/globalCallables.js +88 -84
- package/dist/globalCallables.js.map +1 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +389 -94
- package/dist/interfaces.js +13 -2
- package/dist/interfaces.js.map +1 -1
- package/dist/lexer/Lexer.d.ts +12 -0
- package/dist/lexer/Lexer.js +28 -8
- package/dist/lexer/Lexer.js.map +1 -1
- package/dist/lexer/Lexer.spec.js +40 -0
- package/dist/lexer/Lexer.spec.js.map +1 -1
- package/dist/lexer/Token.d.ts +4 -0
- package/dist/lexer/Token.js.map +1 -1
- package/dist/lexer/TokenKind.d.ts +5 -0
- package/dist/lexer/TokenKind.js +14 -2
- package/dist/lexer/TokenKind.js.map +1 -1
- package/dist/parser/AstNode.d.ts +9 -2
- package/dist/parser/AstNode.js +16 -0
- package/dist/parser/AstNode.js.map +1 -1
- package/dist/parser/BrsTranspileState.d.ts +3 -2
- package/dist/parser/BrsTranspileState.js +3 -2
- package/dist/parser/BrsTranspileState.js.map +1 -1
- package/dist/parser/Expression.d.ts +21 -5
- package/dist/parser/Expression.js +128 -35
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +103 -1
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.d.ts +7 -0
- package/dist/parser/Parser.js +117 -21
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.js +557 -5
- package/dist/parser/Parser.spec.js.map +1 -1
- package/dist/parser/SGParser.d.ts +4 -4
- package/dist/parser/SGParser.js +3 -3
- package/dist/parser/SGParser.js.map +1 -1
- package/dist/parser/SGParser.spec.js +2 -2
- package/dist/parser/SGParser.spec.js.map +1 -1
- package/dist/parser/SGTypes.d.ts +2 -2
- package/dist/parser/Statement.d.ts +37 -12
- package/dist/parser/Statement.js +153 -46
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/tests/Parser.spec.js +2 -1
- package/dist/parser/tests/Parser.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/For.spec.js +16 -8
- package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/ForEach.spec.js +12 -6
- package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/While.spec.js +8 -4
- package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
- package/dist/parser/tests/expression/Call.spec.js +4 -4
- package/dist/parser/tests/expression/Call.spec.js.map +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +29 -29
- package/dist/parser/tests/expression/NullCoalescenceExpression.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/SourceLiteralExpression.spec.js +24 -24
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js +75 -36
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +36 -36
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
- 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/ConstStatement.spec.js +71 -22
- package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Continue.spec.js +2 -2
- package/dist/parser/tests/statement/Continue.spec.js.map +1 -1
- package/dist/parser/tests/statement/Enum.spec.js +38 -285
- package/dist/parser/tests/statement/Enum.spec.js.map +1 -1
- package/dist/parser/tests/statement/For.spec.js +6 -6
- package/dist/parser/tests/statement/For.spec.js.map +1 -1
- package/dist/parser/tests/statement/ForEach.spec.js +4 -4
- package/dist/parser/tests/statement/ForEach.spec.js.map +1 -1
- package/dist/parser/tests/statement/InterfaceStatement.spec.js +26 -10
- package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/PrintStatement.spec.js +16 -13
- package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/ReturnStatement.spec.js +5 -3
- package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Set.spec.js +26 -13
- package/dist/parser/tests/statement/Set.spec.js.map +1 -1
- package/dist/preprocessor/Manifest.d.ts +1 -1
- package/dist/preprocessor/Manifest.js +2 -2
- package/dist/preprocessor/Manifest.js.map +1 -1
- package/dist/roku-types/data.json +243 -293
- package/dist/roku-types/index.d.ts +17 -38
- package/dist/types/ArrayType.d.ts +4 -1
- package/dist/types/ArrayType.js +46 -6
- package/dist/types/ArrayType.js.map +1 -1
- package/dist/types/ArrayType.spec.js +32 -3
- 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 +2 -1
- package/dist/types/BooleanType.js +8 -2
- package/dist/types/BooleanType.js.map +1 -1
- package/dist/types/BscType.d.ts +10 -6
- package/dist/types/BscType.js +69 -16
- package/dist/types/BscType.js.map +1 -1
- package/dist/types/BscTypeKind.d.ts +3 -0
- package/dist/types/BscTypeKind.js +3 -0
- package/dist/types/BscTypeKind.js.map +1 -1
- package/dist/types/BuiltInInterfaceAdder.d.ts +23 -0
- package/dist/types/BuiltInInterfaceAdder.js +157 -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 +10 -4
- package/dist/types/ClassType.js +32 -5
- package/dist/types/ClassType.js.map +1 -1
- package/dist/types/ClassType.spec.js +5 -3
- package/dist/types/ClassType.spec.js.map +1 -1
- 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 +2 -1
- package/dist/types/DoubleType.js +9 -2
- package/dist/types/DoubleType.js.map +1 -1
- package/dist/types/DynamicType.d.ts +2 -2
- package/dist/types/DynamicType.js +3 -1
- package/dist/types/DynamicType.js.map +1 -1
- package/dist/types/EnumType.d.ts +24 -6
- package/dist/types/EnumType.js +29 -7
- package/dist/types/EnumType.js.map +1 -1
- package/dist/types/FloatType.d.ts +2 -1
- package/dist/types/FloatType.js +9 -2
- package/dist/types/FloatType.js.map +1 -1
- package/dist/types/FunctionType.d.ts +8 -20
- package/dist/types/FunctionType.js +17 -45
- package/dist/types/FunctionType.js.map +1 -1
- package/dist/types/InheritableType.d.ts +7 -4
- package/dist/types/InheritableType.js +67 -3
- package/dist/types/InheritableType.js.map +1 -1
- package/dist/types/IntegerType.d.ts +2 -1
- package/dist/types/IntegerType.js +9 -2
- package/dist/types/IntegerType.js.map +1 -1
- package/dist/types/InterfaceType.d.ts +6 -4
- package/dist/types/InterfaceType.js +8 -11
- package/dist/types/InterfaceType.js.map +1 -1
- package/dist/types/InterfaceType.spec.js +30 -2
- package/dist/types/InterfaceType.spec.js.map +1 -1
- package/dist/types/InvalidType.d.ts +2 -1
- package/dist/types/InvalidType.js +7 -1
- package/dist/types/InvalidType.js.map +1 -1
- package/dist/types/LongIntegerType.d.ts +2 -1
- package/dist/types/LongIntegerType.js +9 -2
- package/dist/types/LongIntegerType.js.map +1 -1
- package/dist/types/NamespaceType.d.ts +2 -1
- package/dist/types/NamespaceType.js +3 -0
- package/dist/types/NamespaceType.js.map +1 -1
- package/dist/types/ObjectType.d.ts +2 -2
- package/dist/types/ObjectType.js +5 -10
- package/dist/types/ObjectType.js.map +1 -1
- package/dist/types/ReferenceType.d.ts +15 -3
- package/dist/types/ReferenceType.js +173 -24
- package/dist/types/ReferenceType.js.map +1 -1
- package/dist/types/ReferenceType.spec.js +21 -6
- package/dist/types/ReferenceType.spec.js.map +1 -1
- package/dist/types/StringType.d.ts +2 -1
- package/dist/types/StringType.js +9 -2
- package/dist/types/StringType.js.map +1 -1
- package/dist/types/TypedFunctionType.d.ts +33 -0
- package/dist/types/TypedFunctionType.js +106 -0
- package/dist/types/TypedFunctionType.js.map +1 -0
- package/dist/types/TypedFunctionType.spec.d.ts +1 -0
- package/dist/types/TypedFunctionType.spec.js +122 -0
- package/dist/types/TypedFunctionType.spec.js.map +1 -0
- package/dist/types/UninitializedType.d.ts +2 -1
- package/dist/types/UninitializedType.js +1 -1
- package/dist/types/UninitializedType.js.map +1 -1
- package/dist/types/UnionType.d.ts +4 -2
- package/dist/types/UnionType.js +36 -4
- package/dist/types/UnionType.js.map +1 -1
- package/dist/types/UnionType.spec.js +46 -19
- package/dist/types/UnionType.spec.js.map +1 -1
- package/dist/types/VoidType.d.ts +2 -1
- package/dist/types/VoidType.js +7 -2
- package/dist/types/VoidType.js.map +1 -1
- package/dist/types/helper.spec.js +15 -0
- package/dist/types/helper.spec.js.map +1 -1
- package/dist/types/helpers.d.ts +5 -0
- package/dist/types/helpers.js +50 -3
- package/dist/types/helpers.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/util.d.ts +71 -15
- package/dist/util.js +578 -150
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.d.ts +0 -1
- package/dist/validators/ClassValidator.js +0 -22
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +3 -2
- package/dist/astUtils/AstEditor.js.map +0 -1
- package/dist/astUtils/AstEditor.spec.js.map +0 -1
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +0 -1
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +0 -31
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +0 -1
- package/dist/types/FunctionType.spec.js +0 -23
- package/dist/types/FunctionType.spec.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/{types/FunctionType.spec.d.ts → bscPlugin/serialize/BslibInjector.spec.d.ts} +0 -0
package/dist/Program.js
CHANGED
|
@@ -4,11 +4,8 @@ exports.Program = void 0;
|
|
|
4
4
|
const assert = require("assert");
|
|
5
5
|
const fsExtra = require("fs-extra");
|
|
6
6
|
const path = require("path");
|
|
7
|
-
const vscode_languageserver_1 = require("vscode-languageserver");
|
|
8
7
|
const Scope_1 = require("./Scope");
|
|
9
8
|
const DiagnosticMessages_1 = require("./DiagnosticMessages");
|
|
10
|
-
const BrsFile_1 = require("./files/BrsFile");
|
|
11
|
-
const XmlFile_1 = require("./files/XmlFile");
|
|
12
9
|
const util_1 = require("./util");
|
|
13
10
|
const XmlScope_1 = require("./XmlScope");
|
|
14
11
|
const DiagnosticFilterer_1 = require("./DiagnosticFilterer");
|
|
@@ -21,8 +18,7 @@ const vscode_uri_1 = require("vscode-uri");
|
|
|
21
18
|
const PluginInterface_1 = require("./PluginInterface");
|
|
22
19
|
const reflection_1 = require("./astUtils/reflection");
|
|
23
20
|
const BscPlugin_1 = require("./bscPlugin/BscPlugin");
|
|
24
|
-
const
|
|
25
|
-
const roku_deploy_1 = require("roku-deploy");
|
|
21
|
+
const Editor_1 = require("./astUtils/Editor");
|
|
26
22
|
const CallExpressionInfo_1 = require("./bscPlugin/CallExpressionInfo");
|
|
27
23
|
const SignatureHelpUtil_1 = require("./bscPlugin/SignatureHelpUtil");
|
|
28
24
|
const DiagnosticSeverityAdjuster_1 = require("./DiagnosticSeverityAdjuster");
|
|
@@ -33,14 +29,18 @@ const BooleanType_1 = require("./types/BooleanType");
|
|
|
33
29
|
const DoubleType_1 = require("./types/DoubleType");
|
|
34
30
|
const DynamicType_1 = require("./types/DynamicType");
|
|
35
31
|
const FloatType_1 = require("./types/FloatType");
|
|
36
|
-
const FunctionType_1 = require("./types/FunctionType");
|
|
37
32
|
const LongIntegerType_1 = require("./types/LongIntegerType");
|
|
38
33
|
const ObjectType_1 = require("./types/ObjectType");
|
|
39
34
|
const VoidType_1 = require("./types/VoidType");
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const
|
|
35
|
+
const FunctionType_1 = require("./types/FunctionType");
|
|
36
|
+
const Factory_1 = require("./files/Factory");
|
|
37
|
+
const ActionPipeline_1 = require("./ActionPipeline");
|
|
38
|
+
const LazyFileData_1 = require("./files/LazyFileData");
|
|
39
|
+
const roku_deploy_1 = require("roku-deploy");
|
|
40
|
+
const roku_types_1 = require("./roku-types");
|
|
41
|
+
const ComponentType_1 = require("./types/ComponentType");
|
|
42
|
+
const types_1 = require("./types");
|
|
43
|
+
const BuiltInInterfaceAdder_1 = require("./types/BuiltInInterfaceAdder");
|
|
44
44
|
const bslibNonAliasedRokuModulesPkgPath = (0, util_1.standardizePath) `source/roku_modules/rokucommunity_bslib/bslib.brs`;
|
|
45
45
|
const bslibAliasedRokuModulesPkgPath = (0, util_1.standardizePath) `source/roku_modules/bslib/bslib.brs`;
|
|
46
46
|
class Program {
|
|
@@ -50,7 +50,10 @@ class Program {
|
|
|
50
50
|
*/
|
|
51
51
|
options, logger, plugins) {
|
|
52
52
|
this.options = options;
|
|
53
|
-
|
|
53
|
+
/**
|
|
54
|
+
* An editor that plugins can use to modify program-level things during the build flow. Don't use this to edit files (they have their own `.editor`)
|
|
55
|
+
*/
|
|
56
|
+
this.editor = new Editor_1.Editor();
|
|
54
57
|
/**
|
|
55
58
|
* A graph of all files and their dependencies.
|
|
56
59
|
* For example:
|
|
@@ -65,11 +68,21 @@ class Program {
|
|
|
65
68
|
* Should only be set from `this.validate()`
|
|
66
69
|
*/
|
|
67
70
|
this.diagnostics = [];
|
|
71
|
+
this.fileSymbolInformation = new Map();
|
|
68
72
|
/**
|
|
69
73
|
* A map of every file loaded into this program, indexed by its original file location
|
|
70
74
|
*/
|
|
71
75
|
this.files = {};
|
|
72
|
-
|
|
76
|
+
/**
|
|
77
|
+
* A map of every file loaded into this program, indexed by its destPath
|
|
78
|
+
*/
|
|
79
|
+
this.destMap = new Map();
|
|
80
|
+
/**
|
|
81
|
+
* Plugins can contribute multiple virtual files for a single physical file.
|
|
82
|
+
* This collection links the virtual files back to the physical file that produced them.
|
|
83
|
+
* The key is the standardized and lower-cased srcPath
|
|
84
|
+
*/
|
|
85
|
+
this.fileClusters = new Map();
|
|
73
86
|
this.scopes = {};
|
|
74
87
|
/**
|
|
75
88
|
* A map of every component currently loaded into the program, indexed by the component name.
|
|
@@ -78,6 +91,13 @@ class Program {
|
|
|
78
91
|
* but if you do, only ever use the component at index 0.
|
|
79
92
|
*/
|
|
80
93
|
this.components = {};
|
|
94
|
+
/**
|
|
95
|
+
* Keeps a set of all the components that need to have their types updated during the current validation cycle
|
|
96
|
+
*/
|
|
97
|
+
this.componentSymbolsToUpdate = new Set();
|
|
98
|
+
this.lastValidationInfo = new Map();
|
|
99
|
+
this.getTranspiledFileContentsPipeline = new ActionPipeline_1.ActionPipeline();
|
|
100
|
+
this.buildPipeline = new ActionPipeline_1.ActionPipeline();
|
|
81
101
|
this.options = util_1.util.normalizeConfig(options);
|
|
82
102
|
this.logger = logger || new Logger_1.Logger(options.logLevel);
|
|
83
103
|
this.plugins = plugins || new PluginInterface_1.default([], { logger: this.logger });
|
|
@@ -86,6 +106,7 @@ class Program {
|
|
|
86
106
|
//normalize the root dir path
|
|
87
107
|
this.options.rootDir = util_1.util.getRootDir(this.options);
|
|
88
108
|
this.createGlobalScope();
|
|
109
|
+
this.fileFactory = new Factory_1.FileFactory(this);
|
|
89
110
|
}
|
|
90
111
|
createGlobalScope() {
|
|
91
112
|
//create the 'global' scope
|
|
@@ -95,36 +116,85 @@ class Program {
|
|
|
95
116
|
this.populateGlobalSymbolTable();
|
|
96
117
|
//hardcode the files list for global scope to only contain the global file
|
|
97
118
|
this.globalScope.getAllFiles = () => [globalCallables_1.globalFile];
|
|
119
|
+
globalCallables_1.globalFile.isValidated = true;
|
|
98
120
|
this.globalScope.validate();
|
|
99
121
|
//for now, disable validation of global scope because the global files have some duplicate method declarations
|
|
100
122
|
this.globalScope.getDiagnostics = () => [];
|
|
101
123
|
//TODO we might need to fix this because the isValidated clears stuff now
|
|
102
124
|
this.globalScope.isValidated = true;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
125
|
+
}
|
|
126
|
+
recursivelyAddNodeToSymbolTable(nodeData) {
|
|
127
|
+
if (!nodeData) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
let nodeType;
|
|
131
|
+
const nodeName = util_1.util.getSgNodeTypeName(nodeData.name);
|
|
132
|
+
if (!this.globalScope.symbolTable.hasSymbol(nodeName, SymbolTable_1.SymbolTypeFlag.typetime)) {
|
|
133
|
+
let parentNode;
|
|
134
|
+
if (nodeData.extends) {
|
|
135
|
+
const parentNodeData = roku_types_1.nodes[nodeData.extends.name.toLowerCase()];
|
|
136
|
+
try {
|
|
137
|
+
parentNode = this.recursivelyAddNodeToSymbolTable(parentNodeData);
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
console.log(error, nodeData);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
nodeType = new ComponentType_1.ComponentType(nodeData.name, parentNode);
|
|
144
|
+
nodeType.addBuiltInInterfaces();
|
|
145
|
+
this.globalScope.symbolTable.addSymbol(nodeName, { description: nodeData.description }, nodeType, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
nodeType = this.globalScope.symbolTable.getSymbolType(nodeName, { flags: SymbolTable_1.SymbolTypeFlag.typetime });
|
|
149
|
+
}
|
|
150
|
+
return nodeType;
|
|
107
151
|
}
|
|
108
152
|
/**
|
|
109
153
|
* Do all setup required for the global symbol table.
|
|
110
154
|
*/
|
|
111
155
|
populateGlobalSymbolTable() {
|
|
112
156
|
//Setup primitive types in global symbolTable
|
|
113
|
-
//TODO: Need to handle Array types
|
|
114
157
|
this.globalScope.symbolTable.addSymbol('boolean', undefined, BooleanType_1.BooleanType.instance, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
115
158
|
this.globalScope.symbolTable.addSymbol('double', undefined, DoubleType_1.DoubleType.instance, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
116
159
|
this.globalScope.symbolTable.addSymbol('dynamic', undefined, DynamicType_1.DynamicType.instance, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
117
160
|
this.globalScope.symbolTable.addSymbol('float', undefined, FloatType_1.FloatType.instance, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
118
|
-
this.globalScope.symbolTable.addSymbol('function', undefined, new FunctionType_1.FunctionType(
|
|
161
|
+
this.globalScope.symbolTable.addSymbol('function', undefined, new FunctionType_1.FunctionType(), SymbolTable_1.SymbolTypeFlag.typetime);
|
|
119
162
|
this.globalScope.symbolTable.addSymbol('integer', undefined, IntegerType_1.IntegerType.instance, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
120
163
|
this.globalScope.symbolTable.addSymbol('longinteger', undefined, LongIntegerType_1.LongIntegerType.instance, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
121
164
|
this.globalScope.symbolTable.addSymbol('object', undefined, new ObjectType_1.ObjectType(), SymbolTable_1.SymbolTypeFlag.typetime);
|
|
122
165
|
this.globalScope.symbolTable.addSymbol('string', undefined, StringType_1.StringType.instance, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
123
166
|
this.globalScope.symbolTable.addSymbol('void', undefined, VoidType_1.VoidType.instance, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
this.globalScope.symbolTable.addSymbol(
|
|
167
|
+
BuiltInInterfaceAdder_1.BuiltInInterfaceAdder.getLookupTable = () => this.globalScope.symbolTable;
|
|
168
|
+
for (const callable of globalCallables_1.globalCallables) {
|
|
169
|
+
this.globalScope.symbolTable.addSymbol(callable.name, { description: callable.shortDescription }, callable.type, SymbolTable_1.SymbolTypeFlag.runtime);
|
|
170
|
+
}
|
|
171
|
+
for (const componentData of Object.values(roku_types_1.components)) {
|
|
172
|
+
const nodeType = new types_1.InterfaceType(componentData.name);
|
|
173
|
+
nodeType.addBuiltInInterfaces();
|
|
174
|
+
this.globalScope.symbolTable.addSymbol(componentData.name, { description: componentData.description }, nodeType, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
127
175
|
}
|
|
176
|
+
for (const ifaceData of Object.values(roku_types_1.interfaces)) {
|
|
177
|
+
const nodeType = new types_1.InterfaceType(ifaceData.name);
|
|
178
|
+
nodeType.addBuiltInInterfaces();
|
|
179
|
+
this.globalScope.symbolTable.addSymbol(ifaceData.name, { description: ifaceData.description }, nodeType, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
180
|
+
}
|
|
181
|
+
for (const eventData of Object.values(roku_types_1.events)) {
|
|
182
|
+
const nodeType = new types_1.InterfaceType(eventData.name);
|
|
183
|
+
nodeType.addBuiltInInterfaces();
|
|
184
|
+
this.globalScope.symbolTable.addSymbol(eventData.name, { description: eventData.description }, nodeType, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
185
|
+
}
|
|
186
|
+
for (const nodeData of Object.values(roku_types_1.nodes)) {
|
|
187
|
+
this.recursivelyAddNodeToSymbolTable(nodeData);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
addFileSymbolInfo(file) {
|
|
191
|
+
this.fileSymbolInformation.set(file.pkgPath, {
|
|
192
|
+
provides: file.providedSymbols,
|
|
193
|
+
requires: file.requiredSymbols
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
getFileSymbolInfo(file) {
|
|
197
|
+
return this.fileSymbolInformation.get(file.pkgPath);
|
|
128
198
|
}
|
|
129
199
|
/**
|
|
130
200
|
* The path to bslib.brs (the BrightScript runtime for certain BrighterScript features)
|
|
@@ -140,7 +210,7 @@ class Program {
|
|
|
140
210
|
//default to the embedded version
|
|
141
211
|
}
|
|
142
212
|
else {
|
|
143
|
-
return
|
|
213
|
+
return `${this.options.bslibDestinationDir}${path.sep}bslib.brs`;
|
|
144
214
|
}
|
|
145
215
|
}
|
|
146
216
|
get bslibPrefix() {
|
|
@@ -153,10 +223,6 @@ class Program {
|
|
|
153
223
|
}
|
|
154
224
|
addScope(scope) {
|
|
155
225
|
this.scopes[scope.name] = scope;
|
|
156
|
-
this.plugins.emit('afterScopeCreate', {
|
|
157
|
-
program: this,
|
|
158
|
-
scope: scope
|
|
159
|
-
});
|
|
160
226
|
}
|
|
161
227
|
/**
|
|
162
228
|
* Get the component with the specified name
|
|
@@ -165,7 +231,7 @@ class Program {
|
|
|
165
231
|
var _a;
|
|
166
232
|
if (componentName) {
|
|
167
233
|
//return the first compoment in the list with this name
|
|
168
|
-
//(components are ordered in this list by
|
|
234
|
+
//(components are ordered in this list by destPath to ensure consistency)
|
|
169
235
|
return (_a = this.components[componentName.toLowerCase()]) === null || _a === void 0 ? void 0 : _a[0];
|
|
170
236
|
}
|
|
171
237
|
else {
|
|
@@ -176,8 +242,7 @@ class Program {
|
|
|
176
242
|
* Register (or replace) the reference to a component in the component map
|
|
177
243
|
*/
|
|
178
244
|
registerComponent(xmlFile, scope) {
|
|
179
|
-
|
|
180
|
-
const key = ((_b = (_a = xmlFile.componentName) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : xmlFile.pkgPath).toLowerCase();
|
|
245
|
+
const key = this.getComponentKey(xmlFile);
|
|
181
246
|
if (!this.components[key]) {
|
|
182
247
|
this.components[key] = [];
|
|
183
248
|
}
|
|
@@ -186,8 +251,8 @@ class Program {
|
|
|
186
251
|
scope: scope
|
|
187
252
|
});
|
|
188
253
|
this.components[key].sort((a, b) => {
|
|
189
|
-
const pathA = a.file.
|
|
190
|
-
const pathB = b.file.
|
|
254
|
+
const pathA = a.file.destPath.toLowerCase();
|
|
255
|
+
const pathB = b.file.destPath.toLowerCase();
|
|
191
256
|
if (pathA < pathB) {
|
|
192
257
|
return -1;
|
|
193
258
|
}
|
|
@@ -197,13 +262,13 @@ class Program {
|
|
|
197
262
|
return 0;
|
|
198
263
|
});
|
|
199
264
|
this.syncComponentDependencyGraph(this.components[key]);
|
|
265
|
+
this.addDeferredComponentTypeSymbolCreation(xmlFile);
|
|
200
266
|
}
|
|
201
267
|
/**
|
|
202
268
|
* Remove the specified component from the components map
|
|
203
269
|
*/
|
|
204
270
|
unregisterComponent(xmlFile) {
|
|
205
|
-
|
|
206
|
-
const key = ((_b = (_a = xmlFile.componentName) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : xmlFile.pkgPath).toLowerCase();
|
|
271
|
+
const key = this.getComponentKey(xmlFile);
|
|
207
272
|
const arr = this.components[key] || [];
|
|
208
273
|
for (let i = 0; i < arr.length; i++) {
|
|
209
274
|
if (arr[i].file === xmlFile) {
|
|
@@ -212,6 +277,44 @@ class Program {
|
|
|
212
277
|
}
|
|
213
278
|
}
|
|
214
279
|
this.syncComponentDependencyGraph(arr);
|
|
280
|
+
this.addDeferredComponentTypeSymbolCreation(xmlFile);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Adds a component described in an XML to the set of components that needs to be updated this validation cycle.
|
|
284
|
+
* @param xmlFile XML file with <component> tag
|
|
285
|
+
*/
|
|
286
|
+
addDeferredComponentTypeSymbolCreation(xmlFile) {
|
|
287
|
+
var _a;
|
|
288
|
+
this.componentSymbolsToUpdate.add({ componentKey: this.getComponentKey(xmlFile), componentName: (_a = xmlFile.componentName) === null || _a === void 0 ? void 0 : _a.text });
|
|
289
|
+
}
|
|
290
|
+
getComponentKey(xmlFile) {
|
|
291
|
+
var _a, _b;
|
|
292
|
+
return ((_b = (_a = xmlFile.componentName) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : xmlFile.pkgPath).toLowerCase();
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Updates the global symbol table with the first component in this.components to have the same name as the component in the file
|
|
296
|
+
* @param componentKey key getting a component from `this.components`
|
|
297
|
+
* @param componentName the unprefixed name of the component that will be added (e.g. 'MyLabel' NOT 'roSgNodeMyLabel')
|
|
298
|
+
*/
|
|
299
|
+
updateComponentSymbolInGlobalScope(componentKey, componentName) {
|
|
300
|
+
const symbolName = componentName ? util_1.util.getSgNodeTypeName(componentName) : undefined;
|
|
301
|
+
if (!symbolName) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
const components = this.components[componentKey] || [];
|
|
305
|
+
// Remove any existing symbols that match
|
|
306
|
+
this.globalScope.symbolTable.removeSymbol(symbolName);
|
|
307
|
+
// There is a component that can be added - use it.
|
|
308
|
+
if (components.length > 0) {
|
|
309
|
+
const componentScope = components[0].scope;
|
|
310
|
+
// TODO: May need to link symbol tables to get correct types for callfuncs
|
|
311
|
+
// componentScope.linkSymbolTable();
|
|
312
|
+
const componentType = componentScope.getComponentType();
|
|
313
|
+
if (componentType) {
|
|
314
|
+
this.globalScope.symbolTable.addSymbol(symbolName, {}, componentType, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
315
|
+
}
|
|
316
|
+
// TODO: Remember to unlink! componentScope.unlinkSymbolTable();
|
|
317
|
+
}
|
|
215
318
|
}
|
|
216
319
|
/**
|
|
217
320
|
* re-attach the dependency graph with a new key for any component who changed
|
|
@@ -225,6 +328,7 @@ class Program {
|
|
|
225
328
|
//attach (or re-attach) the dependencyGraph for every component whose position changed
|
|
226
329
|
if (file.dependencyGraphIndex !== i) {
|
|
227
330
|
file.dependencyGraphIndex = i;
|
|
331
|
+
this.dependencyGraph.addOrReplace(file.dependencyGraphKey, file.dependencies);
|
|
228
332
|
file.attachDependencyGraph(this.dependencyGraph);
|
|
229
333
|
scope.attachDependencyGraph(this.dependencyGraph);
|
|
230
334
|
}
|
|
@@ -261,7 +365,7 @@ class Program {
|
|
|
261
365
|
//get the diagnostics from all unreferenced files
|
|
262
366
|
let unreferencedFiles = this.getUnreferencedFiles();
|
|
263
367
|
for (let file of unreferencedFiles) {
|
|
264
|
-
diagnostics.push(...file.
|
|
368
|
+
diagnostics.push(...file.diagnostics);
|
|
265
369
|
}
|
|
266
370
|
const filteredDiagnostics = this.logger.time(Logger_1.LogLevel.debug, ['filter diagnostics'], () => {
|
|
267
371
|
//filter out diagnostics based on our diagnostic filters
|
|
@@ -286,11 +390,9 @@ class Program {
|
|
|
286
390
|
hasFile(filePath, normalizePath = true) {
|
|
287
391
|
return !!this.getFile(filePath, normalizePath);
|
|
288
392
|
}
|
|
289
|
-
getPkgPath(...args) {
|
|
290
|
-
throw new Error('Not implemented');
|
|
291
|
-
}
|
|
292
393
|
/**
|
|
293
394
|
* roku filesystem is case INsensitive, so find the scope by key case insensitive
|
|
395
|
+
* @param scopeName xml scope names are their `destPath`. Source scope is stored with the key `"source"`
|
|
294
396
|
*/
|
|
295
397
|
getScopeByName(scopeName) {
|
|
296
398
|
if (!scopeName) {
|
|
@@ -298,8 +400,8 @@ class Program {
|
|
|
298
400
|
}
|
|
299
401
|
//most scopes are xml file pkg paths. however, the ones that are not are single names like "global" and "scope",
|
|
300
402
|
//so it's safe to run the standardizePkgPath method
|
|
301
|
-
scopeName = (0, util_1.standardizePath) `${scopeName}`;
|
|
302
|
-
let key = Object.keys(this.scopes).find(x => x.toLowerCase() === scopeName
|
|
403
|
+
scopeName = (0, util_1.standardizePath) `${scopeName.toLowerCase()}`;
|
|
404
|
+
let key = Object.keys(this.scopes).find(x => x.toLowerCase() === scopeName);
|
|
303
405
|
return this.scopes[key];
|
|
304
406
|
}
|
|
305
407
|
/**
|
|
@@ -319,8 +421,14 @@ class Program {
|
|
|
319
421
|
* Update internal maps with this file reference
|
|
320
422
|
*/
|
|
321
423
|
assignFile(file) {
|
|
424
|
+
const fileAddEvent = {
|
|
425
|
+
file: file,
|
|
426
|
+
program: this
|
|
427
|
+
};
|
|
428
|
+
this.plugins.emit('beforeFileAdd', fileAddEvent);
|
|
322
429
|
this.files[file.srcPath.toLowerCase()] = file;
|
|
323
|
-
this.
|
|
430
|
+
this.destMap.set(file.destPath.toLowerCase(), file);
|
|
431
|
+
this.plugins.emit('afterFileAdd', fileAddEvent);
|
|
324
432
|
return file;
|
|
325
433
|
}
|
|
326
434
|
/**
|
|
@@ -328,99 +436,102 @@ class Program {
|
|
|
328
436
|
*/
|
|
329
437
|
unassignFile(file) {
|
|
330
438
|
delete this.files[file.srcPath.toLowerCase()];
|
|
331
|
-
|
|
439
|
+
this.destMap.delete(file.destPath.toLowerCase());
|
|
332
440
|
return file;
|
|
333
441
|
}
|
|
334
|
-
setFile(fileParam,
|
|
442
|
+
setFile(fileParam, fileData) {
|
|
335
443
|
//normalize the file paths
|
|
336
|
-
const { srcPath,
|
|
444
|
+
const { srcPath, destPath } = this.getPaths(fileParam, this.options.rootDir);
|
|
337
445
|
let file = this.logger.time(Logger_1.LogLevel.debug, ['Program.setFile()', chalk_1.default.green(srcPath)], () => {
|
|
446
|
+
var _a, _b, _c;
|
|
338
447
|
//if the file is already loaded, remove it
|
|
339
448
|
if (this.hasFile(srcPath)) {
|
|
340
|
-
this.removeFile(srcPath);
|
|
449
|
+
this.removeFile(srcPath, true, true);
|
|
341
450
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
source: fileContents
|
|
356
|
-
};
|
|
357
|
-
this.plugins.emit('beforeFileParse', beforeFileParseEvent);
|
|
358
|
-
this.logger.time(Logger_1.LogLevel.debug, ['parse', chalk_1.default.green(srcPath)], () => {
|
|
359
|
-
brsFile.parse(beforeFileParseEvent.source);
|
|
360
|
-
});
|
|
361
|
-
//notify plugins that this file has finished parsing
|
|
362
|
-
this.plugins.emit('afterFileParse', {
|
|
363
|
-
program: this,
|
|
364
|
-
file: brsFile
|
|
365
|
-
});
|
|
366
|
-
file = brsFile;
|
|
367
|
-
brsFile.attachDependencyGraph(this.dependencyGraph);
|
|
451
|
+
const data = new LazyFileData_1.LazyFileData(fileData);
|
|
452
|
+
const event = new ProvideFileEventInternal(this, srcPath, destPath, data, this.fileFactory);
|
|
453
|
+
this.plugins.emit('beforeProvideFile', event);
|
|
454
|
+
this.plugins.emit('provideFile', event);
|
|
455
|
+
this.plugins.emit('afterProvideFile', event);
|
|
456
|
+
//if no files were provided, create a AssetFile to represent it.
|
|
457
|
+
if (event.files.length === 0) {
|
|
458
|
+
event.files.push(this.fileFactory.AssetFile({
|
|
459
|
+
srcPath: event.srcPath,
|
|
460
|
+
destPath: event.destPath,
|
|
461
|
+
pkgPath: event.destPath,
|
|
462
|
+
data: data
|
|
463
|
+
}));
|
|
368
464
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
program: this,
|
|
378
|
-
srcPath: srcPath,
|
|
379
|
-
source: fileContents
|
|
380
|
-
};
|
|
381
|
-
this.plugins.emit('beforeFileParse', event);
|
|
382
|
-
this.logger.time(Logger_1.LogLevel.debug, ['parse', chalk_1.default.green(srcPath)], () => {
|
|
383
|
-
xmlFile.parse(event.source);
|
|
384
|
-
});
|
|
385
|
-
//notify plugins that this file has finished parsing
|
|
386
|
-
this.plugins.emit('afterFileParse', {
|
|
387
|
-
program: this,
|
|
388
|
-
file: xmlFile
|
|
389
|
-
});
|
|
390
|
-
file = xmlFile;
|
|
391
|
-
//create a new scope for this xml file
|
|
392
|
-
let scope = new XmlScope_1.XmlScope(xmlFile, this);
|
|
393
|
-
this.addScope(scope);
|
|
394
|
-
//register this compoent now that we have parsed it and know its component name
|
|
395
|
-
this.registerComponent(xmlFile, scope);
|
|
465
|
+
//find the file instance for the srcPath that triggered this action.
|
|
466
|
+
const primaryFile = event.files.find(x => x.srcPath === srcPath);
|
|
467
|
+
if (!primaryFile) {
|
|
468
|
+
throw new Error(`No file provided for srcPath '${srcPath}'. Instead, received ${JSON.stringify(event.files.map(x => ({
|
|
469
|
+
type: x.type,
|
|
470
|
+
srcPath: x.srcPath,
|
|
471
|
+
destPath: x.destPath
|
|
472
|
+
})))}`);
|
|
396
473
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
474
|
+
//link the virtual files to the primary file
|
|
475
|
+
this.fileClusters.set((_a = primaryFile.srcPath) === null || _a === void 0 ? void 0 : _a.toLowerCase(), event.files);
|
|
476
|
+
for (const file of event.files) {
|
|
477
|
+
file.srcPath = (0, util_1.standardizePath)(file.srcPath);
|
|
478
|
+
if (file.destPath) {
|
|
479
|
+
file.destPath = (0, util_1.standardizePath) `${util_1.util.replaceCaseInsensitive(file.destPath, this.options.rootDir, '')}`;
|
|
480
|
+
}
|
|
481
|
+
if (file.pkgPath) {
|
|
482
|
+
file.pkgPath = (0, util_1.standardizePath) `${util_1.util.replaceCaseInsensitive(file.pkgPath, this.options.rootDir, '')}`;
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
file.pkgPath = file.destPath;
|
|
486
|
+
}
|
|
487
|
+
file.excludeFromOutput = file.excludeFromOutput === true;
|
|
488
|
+
//set the dependencyGraph key for every file to its destPath
|
|
489
|
+
file.dependencyGraphKey = file.destPath.toLowerCase();
|
|
490
|
+
this.assignFile(file);
|
|
491
|
+
//register a callback anytime this file's dependencies change
|
|
492
|
+
if (typeof file.onDependenciesChanged === 'function') {
|
|
493
|
+
(_b = file.disposables) !== null && _b !== void 0 ? _b : (file.disposables = []);
|
|
494
|
+
file.disposables.push(this.dependencyGraph.onchange(file.dependencyGraphKey, file.onDependenciesChanged.bind(file)));
|
|
495
|
+
}
|
|
496
|
+
//register this file (and its dependencies) with the dependency graph
|
|
497
|
+
this.dependencyGraph.addOrReplace(file.dependencyGraphKey, (_c = file.dependencies) !== null && _c !== void 0 ? _c : []);
|
|
498
|
+
//if this is a `source` file, add it to the source scope's dependency list
|
|
499
|
+
if (this.isSourceBrsFile(file)) {
|
|
500
|
+
this.createSourceScope();
|
|
501
|
+
this.dependencyGraph.addDependency('scope:source', file.dependencyGraphKey);
|
|
502
|
+
}
|
|
503
|
+
//if this is an xml file in the components folder, register it as a component
|
|
504
|
+
if (this.isComponentsXmlFile(file)) {
|
|
505
|
+
//create a new scope for this xml file
|
|
506
|
+
let scope = new XmlScope_1.XmlScope(file, this);
|
|
507
|
+
this.addScope(scope);
|
|
508
|
+
//register this compoent now that we have parsed it and know its component name
|
|
509
|
+
this.registerComponent(file, scope);
|
|
510
|
+
//notify plugins that the scope is created and the component is registered
|
|
511
|
+
this.plugins.emit('afterScopeCreate', {
|
|
512
|
+
program: this,
|
|
513
|
+
scope: scope
|
|
514
|
+
});
|
|
515
|
+
}
|
|
405
516
|
}
|
|
406
|
-
return
|
|
517
|
+
return primaryFile;
|
|
407
518
|
});
|
|
408
519
|
return file;
|
|
409
520
|
}
|
|
410
521
|
/**
|
|
411
|
-
* Given a srcPath, a
|
|
522
|
+
* Given a srcPath, a destPath, or both, resolve whichever is missing, relative to rootDir.
|
|
412
523
|
* @param fileParam an object representing file paths
|
|
413
524
|
* @param rootDir must be a pre-normalized path
|
|
414
525
|
*/
|
|
415
526
|
getPaths(fileParam, rootDir) {
|
|
416
527
|
let srcPath;
|
|
417
|
-
let
|
|
528
|
+
let destPath;
|
|
418
529
|
assert.ok(fileParam, 'fileParam is required');
|
|
419
|
-
//lift the
|
|
530
|
+
//lift the path vars from the incoming param
|
|
420
531
|
if (typeof fileParam === 'string') {
|
|
421
532
|
fileParam = this.removePkgPrefix(fileParam);
|
|
422
533
|
srcPath = (0, util_1.standardizePath) `${path.resolve(rootDir, fileParam)}`;
|
|
423
|
-
|
|
534
|
+
destPath = (0, util_1.standardizePath) `${util_1.util.replaceCaseInsensitive(srcPath, rootDir, '')}`;
|
|
424
535
|
}
|
|
425
536
|
else {
|
|
426
537
|
let param = fileParam;
|
|
@@ -431,30 +542,30 @@ class Program {
|
|
|
431
542
|
srcPath = (0, util_1.standardizePath) `${param.srcPath}`;
|
|
432
543
|
}
|
|
433
544
|
if (param.dest) {
|
|
434
|
-
|
|
545
|
+
destPath = (0, util_1.standardizePath) `${this.removePkgPrefix(param.dest)}`;
|
|
435
546
|
}
|
|
436
547
|
if (param.pkgPath) {
|
|
437
|
-
|
|
548
|
+
destPath = (0, util_1.standardizePath) `${this.removePkgPrefix(param.pkgPath)}`;
|
|
438
549
|
}
|
|
439
550
|
}
|
|
440
|
-
//if there's no srcPath, use the
|
|
551
|
+
//if there's no srcPath, use the destPath to build an absolute srcPath
|
|
441
552
|
if (!srcPath) {
|
|
442
|
-
srcPath = (0, util_1.standardizePath) `${rootDir}/${
|
|
553
|
+
srcPath = (0, util_1.standardizePath) `${rootDir}/${destPath}`;
|
|
443
554
|
}
|
|
444
555
|
//coerce srcPath to an absolute path
|
|
445
556
|
if (!path.isAbsolute(srcPath)) {
|
|
446
557
|
srcPath = util_1.util.standardizePath(srcPath);
|
|
447
558
|
}
|
|
448
|
-
//if
|
|
449
|
-
if (!
|
|
450
|
-
|
|
559
|
+
//if destPath isn't set, compute it from the other paths
|
|
560
|
+
if (!destPath) {
|
|
561
|
+
destPath = (0, util_1.standardizePath) `${util_1.util.replaceCaseInsensitive(srcPath, rootDir, '')}`;
|
|
451
562
|
}
|
|
452
563
|
assert.ok(srcPath, 'fileEntry.src is required');
|
|
453
|
-
assert.ok(
|
|
564
|
+
assert.ok(destPath, 'fileEntry.dest is required');
|
|
454
565
|
return {
|
|
455
566
|
srcPath: srcPath,
|
|
456
|
-
//remove leading slash
|
|
457
|
-
|
|
567
|
+
//remove leading slash
|
|
568
|
+
destPath: destPath.replace(/^[\/\\]+/, '')
|
|
458
569
|
};
|
|
459
570
|
}
|
|
460
571
|
/**
|
|
@@ -463,6 +574,18 @@ class Program {
|
|
|
463
574
|
removePkgPrefix(path) {
|
|
464
575
|
return path.replace(/^pkg:\//i, '');
|
|
465
576
|
}
|
|
577
|
+
/**
|
|
578
|
+
* Is this file a .brs file found somewhere within the `pkg:/source/` folder?
|
|
579
|
+
*/
|
|
580
|
+
isSourceBrsFile(file) {
|
|
581
|
+
return !!/^(pkg:\/)?source[\/\\]/.exec(file.destPath);
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Is this file a .brs file found somewhere within the `pkg:/source/` folder?
|
|
585
|
+
*/
|
|
586
|
+
isComponentsXmlFile(file) {
|
|
587
|
+
return (0, reflection_1.isXmlFile)(file) && !!/^(pkg:\/)?components[\/\\]/.exec(file.destPath);
|
|
588
|
+
}
|
|
466
589
|
/**
|
|
467
590
|
* Ensure source scope is created.
|
|
468
591
|
* Note: automatically called internally, and no-op if it exists already.
|
|
@@ -472,6 +595,10 @@ class Program {
|
|
|
472
595
|
const sourceScope = new Scope_1.Scope('source', this, 'scope:source');
|
|
473
596
|
sourceScope.attachDependencyGraph(this.dependencyGraph);
|
|
474
597
|
this.addScope(sourceScope);
|
|
598
|
+
this.plugins.emit('afterScopeCreate', {
|
|
599
|
+
program: this,
|
|
600
|
+
scope: sourceScope
|
|
601
|
+
});
|
|
475
602
|
}
|
|
476
603
|
}
|
|
477
604
|
/**
|
|
@@ -486,46 +613,58 @@ class Program {
|
|
|
486
613
|
}
|
|
487
614
|
/**
|
|
488
615
|
* Remove a file from the program
|
|
489
|
-
* @param filePath can be a srcPath, a
|
|
616
|
+
* @param filePath can be a srcPath, a destPath, or a destPath with leading `pkg:/`
|
|
490
617
|
* @param normalizePath should this function repair and standardize the path? Passing false should have a performance boost if you can guarantee your path is already sanitized
|
|
491
618
|
*/
|
|
492
|
-
removeFile(filePath, normalizePath = true) {
|
|
619
|
+
removeFile(filePath, normalizePath = true, keepSymbolInformation = false) {
|
|
620
|
+
var _a, _b, _c, _d;
|
|
493
621
|
this.logger.debug('Program.removeFile()', filePath);
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
622
|
+
const paths = this.getPaths(filePath, this.options.rootDir);
|
|
623
|
+
//there can be one or more File entries for a single srcPath, so get all of them and remove them all
|
|
624
|
+
const files = (_b = this.fileClusters.get((_a = paths.srcPath) === null || _a === void 0 ? void 0 : _a.toLowerCase())) !== null && _b !== void 0 ? _b : [this.getFile(filePath, normalizePath)];
|
|
625
|
+
for (const file of files) {
|
|
626
|
+
//if a file has already been removed, nothing more needs to be done here
|
|
627
|
+
if (!file || !this.hasFile(file.srcPath)) {
|
|
628
|
+
continue;
|
|
629
|
+
}
|
|
630
|
+
const event = { file: file, program: this };
|
|
631
|
+
this.plugins.emit('beforeFileRemove', event);
|
|
501
632
|
//if there is a scope named the same as this file's path, remove it (i.e. xml scopes)
|
|
502
|
-
let scope = this.scopes[file.
|
|
633
|
+
let scope = this.scopes[file.destPath];
|
|
503
634
|
if (scope) {
|
|
504
635
|
const scopeDisposeEvent = {
|
|
505
636
|
program: this,
|
|
506
637
|
scope: scope
|
|
507
638
|
};
|
|
508
639
|
this.plugins.emit('beforeScopeDispose', scopeDisposeEvent);
|
|
640
|
+
this.plugins.emit('onScopeDispose', scopeDisposeEvent);
|
|
509
641
|
scope.dispose();
|
|
510
642
|
//notify dependencies of this scope that it has been removed
|
|
511
643
|
this.dependencyGraph.remove(scope.dependencyGraphKey);
|
|
512
|
-
delete this.scopes[file.
|
|
644
|
+
delete this.scopes[file.destPath];
|
|
513
645
|
this.plugins.emit('afterScopeDispose', scopeDisposeEvent);
|
|
514
646
|
}
|
|
515
647
|
//remove the file from the program
|
|
516
648
|
this.unassignFile(file);
|
|
517
649
|
this.dependencyGraph.remove(file.dependencyGraphKey);
|
|
518
650
|
//if this is a pkg:/source file, notify the `source` scope that it has changed
|
|
519
|
-
if (
|
|
651
|
+
if (this.isSourceBrsFile(file)) {
|
|
520
652
|
this.dependencyGraph.removeDependency('scope:source', file.dependencyGraphKey);
|
|
653
|
+
if (!keepSymbolInformation) {
|
|
654
|
+
this.fileSymbolInformation.delete(file.pkgPath);
|
|
655
|
+
}
|
|
521
656
|
}
|
|
522
657
|
//if this is a component, remove it from our components map
|
|
523
658
|
if ((0, reflection_1.isXmlFile)(file)) {
|
|
524
659
|
this.unregisterComponent(file);
|
|
525
660
|
}
|
|
661
|
+
//dispose any disposable things on the file
|
|
662
|
+
for (const disposable of (_c = file === null || file === void 0 ? void 0 : file.disposables) !== null && _c !== void 0 ? _c : []) {
|
|
663
|
+
disposable();
|
|
664
|
+
}
|
|
526
665
|
//dispose file
|
|
527
|
-
file === null || file === void 0 ? void 0 : file.dispose();
|
|
528
|
-
this.plugins.emit('
|
|
666
|
+
(_d = file === null || file === void 0 ? void 0 : file.dispose) === null || _d === void 0 ? void 0 : _d.call(file);
|
|
667
|
+
this.plugins.emit('afterFileRemove', event);
|
|
529
668
|
}
|
|
530
669
|
}
|
|
531
670
|
/**
|
|
@@ -533,12 +672,15 @@ class Program {
|
|
|
533
672
|
*/
|
|
534
673
|
validate() {
|
|
535
674
|
this.logger.time(Logger_1.LogLevel.log, ['Validating project'], () => {
|
|
675
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
536
676
|
this.diagnostics = [];
|
|
537
677
|
const programValidateEvent = {
|
|
538
678
|
program: this
|
|
539
679
|
};
|
|
540
680
|
this.plugins.emit('beforeProgramValidate', programValidateEvent);
|
|
681
|
+
this.plugins.emit('onProgramValidate', programValidateEvent);
|
|
541
682
|
//validate every file
|
|
683
|
+
const brsFilesValidated = [];
|
|
542
684
|
for (const file of Object.values(this.files)) {
|
|
543
685
|
//for every unvalidated file, validate it
|
|
544
686
|
if (!file.isValidated) {
|
|
@@ -550,21 +692,118 @@ class Program {
|
|
|
550
692
|
//emit an event to allow plugins to contribute to the file validation process
|
|
551
693
|
this.plugins.emit('onFileValidate', validateFileEvent);
|
|
552
694
|
file.isValidated = true;
|
|
695
|
+
if ((0, reflection_1.isBrsFile)(file)) {
|
|
696
|
+
brsFilesValidated.push(file);
|
|
697
|
+
}
|
|
553
698
|
this.plugins.emit('afterFileValidate', validateFileEvent);
|
|
554
699
|
}
|
|
555
700
|
}
|
|
701
|
+
// build list of all changed symbols in each file that changed
|
|
702
|
+
this.lastValidationInfo.clear();
|
|
703
|
+
for (const file of brsFilesValidated) {
|
|
704
|
+
const fileInfo = {
|
|
705
|
+
symbolsNotDefinedInEveryScope: [],
|
|
706
|
+
duplicateSymbolsInSameScope: [],
|
|
707
|
+
symbolsNotConsistentAcrossScopes: []
|
|
708
|
+
};
|
|
709
|
+
const scopesToCheckForConsistency = this.getScopesForFile(file);
|
|
710
|
+
for (const symbol of file.requiredSymbols) {
|
|
711
|
+
let providedSymbolType;
|
|
712
|
+
let scopesDefiningSymbol = [];
|
|
713
|
+
let scopesAreInconsistent = false;
|
|
714
|
+
for (const scope of scopesToCheckForConsistency) {
|
|
715
|
+
let symbolFoundInScope = false;
|
|
716
|
+
for (const scopeFile of scope.getAllFiles()) {
|
|
717
|
+
if (!(0, reflection_1.isBrsFile)(scopeFile) || scopeFile.isTypedef || scopeFile.hasTypedef) {
|
|
718
|
+
continue;
|
|
719
|
+
}
|
|
720
|
+
const lowerFirstSymbolName = (_b = (_a = symbol.typeChain) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.name.toLowerCase();
|
|
721
|
+
let symbolInThisScope = (_d = (_c = scopeFile.providedSymbols.symbolMap) === null || _c === void 0 ? void 0 : _c.get(symbol.flags)) === null || _d === void 0 ? void 0 : _d.get(lowerFirstSymbolName);
|
|
722
|
+
if (!symbolInThisScope && ((_e = symbol.containingNamespaces) === null || _e === void 0 ? void 0 : _e.length) > 0) {
|
|
723
|
+
const fullNameWithNamespaces = (symbol.containingNamespaces.join('.') + '.' + lowerFirstSymbolName).toLowerCase();
|
|
724
|
+
symbolInThisScope = (_g = (_f = scopeFile.providedSymbols.symbolMap) === null || _f === void 0 ? void 0 : _f.get(symbol.flags)) === null || _g === void 0 ? void 0 : _g.get(fullNameWithNamespaces);
|
|
725
|
+
}
|
|
726
|
+
if (symbolInThisScope) {
|
|
727
|
+
if (symbolFoundInScope) {
|
|
728
|
+
// this is duplicately defined!
|
|
729
|
+
fileInfo.duplicateSymbolsInSameScope.push({ symbol: symbol, scope: scope });
|
|
730
|
+
}
|
|
731
|
+
else {
|
|
732
|
+
symbolFoundInScope = true;
|
|
733
|
+
scopesDefiningSymbol.push(scope);
|
|
734
|
+
//check for consistency across scopes
|
|
735
|
+
if (!providedSymbolType) {
|
|
736
|
+
providedSymbolType = symbolInThisScope.type;
|
|
737
|
+
}
|
|
738
|
+
else {
|
|
739
|
+
//get more general type
|
|
740
|
+
if (providedSymbolType.isEqual(symbolInThisScope.type)) {
|
|
741
|
+
//type in this scope is the same as one we're already checking
|
|
742
|
+
}
|
|
743
|
+
else if (providedSymbolType.isTypeCompatible(symbolInThisScope.type)) {
|
|
744
|
+
//type in this scope is compatible with one we're storing. use most generic
|
|
745
|
+
providedSymbolType = symbolInThisScope.type;
|
|
746
|
+
}
|
|
747
|
+
else if (symbolInThisScope.type.isTypeCompatible(providedSymbolType)) {
|
|
748
|
+
// type we're storing is more generic that the type in this scope
|
|
749
|
+
}
|
|
750
|
+
else {
|
|
751
|
+
// type in this scope is not compatible with other types for this symbol
|
|
752
|
+
scopesAreInconsistent = true;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
if (!symbolFoundInScope) {
|
|
759
|
+
fileInfo.symbolsNotDefinedInEveryScope.push({ symbol: symbol, scope: scope });
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
if (scopesAreInconsistent) {
|
|
763
|
+
fileInfo.symbolsNotConsistentAcrossScopes.push({ symbol: symbol, scopes: scopesDefiningSymbol });
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
this.lastValidationInfo.set(file.srcPath.toLowerCase(), fileInfo);
|
|
767
|
+
}
|
|
768
|
+
this.detectIncompatibleSymbolsAcrossScopes();
|
|
769
|
+
// Build component types for any component that changes
|
|
770
|
+
this.logger.time(Logger_1.LogLevel.info, ['Build component types'], () => {
|
|
771
|
+
for (let { componentKey, componentName } of this.componentSymbolsToUpdate) {
|
|
772
|
+
this.updateComponentSymbolInGlobalScope(componentKey, componentName);
|
|
773
|
+
}
|
|
774
|
+
this.componentSymbolsToUpdate.clear();
|
|
775
|
+
});
|
|
776
|
+
const changedSymbolsMapArr = brsFilesValidated === null || brsFilesValidated === void 0 ? void 0 : brsFilesValidated.map(f => {
|
|
777
|
+
if ((0, reflection_1.isBrsFile)(f)) {
|
|
778
|
+
return f.providedSymbols.changes;
|
|
779
|
+
}
|
|
780
|
+
return null;
|
|
781
|
+
}).filter(x => x);
|
|
782
|
+
const changedSymbols = new Map();
|
|
783
|
+
for (const flag of [SymbolTable_1.SymbolTypeFlag.runtime, SymbolTable_1.SymbolTypeFlag.typetime]) {
|
|
784
|
+
const changedSymbolsSetArr = changedSymbolsMapArr.map(symMap => symMap.get(flag));
|
|
785
|
+
changedSymbols.set(flag, new Set(...changedSymbolsSetArr));
|
|
786
|
+
}
|
|
556
787
|
this.logger.time(Logger_1.LogLevel.info, ['Validate all scopes'], () => {
|
|
557
788
|
for (let scopeName in this.scopes) {
|
|
558
789
|
let scope = this.scopes[scopeName];
|
|
559
|
-
scope.
|
|
560
|
-
scope.validate();
|
|
561
|
-
scope.unlinkSymbolTable();
|
|
790
|
+
scope.validate({ changedFiles: brsFilesValidated, changedSymbols: changedSymbols });
|
|
562
791
|
}
|
|
563
792
|
});
|
|
564
793
|
this.detectDuplicateComponentNames();
|
|
565
794
|
this.plugins.emit('afterProgramValidate', programValidateEvent);
|
|
566
795
|
});
|
|
567
796
|
}
|
|
797
|
+
detectIncompatibleSymbolsAcrossScopes() {
|
|
798
|
+
for (const [lowerFilePath, fileInfo] of this.lastValidationInfo.entries()) {
|
|
799
|
+
const file = this.files[lowerFilePath];
|
|
800
|
+
for (const symbolAndScopes of fileInfo.symbolsNotConsistentAcrossScopes) {
|
|
801
|
+
const typeChainResult = util_1.util.processTypeChain(symbolAndScopes.symbol.typeChain);
|
|
802
|
+
const scopeListName = symbolAndScopes.scopes.map(s => s.name).join(', ');
|
|
803
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.incompatibleSymbolDefinition(typeChainResult.fullNameOfItem, scopeListName)), { file: file, range: typeChainResult.range }));
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
}
|
|
568
807
|
/**
|
|
569
808
|
* Flag all duplicate component names
|
|
570
809
|
*/
|
|
@@ -617,12 +856,13 @@ class Program {
|
|
|
617
856
|
getFile(filePath, normalizePath = true) {
|
|
618
857
|
if (typeof filePath !== 'string') {
|
|
619
858
|
return undefined;
|
|
859
|
+
//is the path absolute (or the `virtual:` prefix)
|
|
620
860
|
}
|
|
621
|
-
else if (
|
|
861
|
+
else if (/^(?:(?:virtual:[\/\\])|(?:\w:)|(?:[\/\\]))/gmi.exec(filePath)) {
|
|
622
862
|
return this.files[(normalizePath ? util_1.util.standardizePath(filePath) : filePath).toLowerCase()];
|
|
623
863
|
}
|
|
624
864
|
else {
|
|
625
|
-
return this.
|
|
865
|
+
return this.destMap.get((normalizePath ? util_1.util.standardizePath(filePath) : filePath).toLowerCase());
|
|
626
866
|
}
|
|
627
867
|
}
|
|
628
868
|
/**
|
|
@@ -664,7 +904,8 @@ class Program {
|
|
|
664
904
|
//look through all files in scope for matches
|
|
665
905
|
for (const scope of this.getScopesForFile(originFile)) {
|
|
666
906
|
for (const file of scope.getAllFiles()) {
|
|
667
|
-
|
|
907
|
+
//skip non-brs files, or files we've already processed
|
|
908
|
+
if (!(0, reflection_1.isBrsFile)(file) || filesSearched.has(file)) {
|
|
668
909
|
continue;
|
|
669
910
|
}
|
|
670
911
|
filesSearched.add(file);
|
|
@@ -697,7 +938,8 @@ class Program {
|
|
|
697
938
|
}
|
|
698
939
|
//look through all files in scope for matches
|
|
699
940
|
for (const file of scope.getOwnFiles()) {
|
|
700
|
-
|
|
941
|
+
//skip non-brs files, or files we've already processed
|
|
942
|
+
if (!(0, reflection_1.isBrsFile)(file) || filesSearched.has(file)) {
|
|
701
943
|
continue;
|
|
702
944
|
}
|
|
703
945
|
filesSearched.add(file);
|
|
@@ -846,60 +1088,12 @@ class Program {
|
|
|
846
1088
|
getReferences(srcPath, position) {
|
|
847
1089
|
//find the file
|
|
848
1090
|
let file = this.getFile(srcPath);
|
|
849
|
-
if (
|
|
850
|
-
return
|
|
1091
|
+
if ((0, reflection_1.isBrsFile)(file) || (0, reflection_1.isXmlFile)(file)) {
|
|
1092
|
+
return file.getReferences(position);
|
|
851
1093
|
}
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
/**
|
|
855
|
-
* Get a list of all script imports, relative to the specified pkgPath
|
|
856
|
-
* @param sourcePkgPath - the pkgPath of the source that wants to resolve script imports.
|
|
857
|
-
*/
|
|
858
|
-
getScriptImportCompletions(sourcePkgPath, scriptImport) {
|
|
859
|
-
let lowerSourcePkgPath = sourcePkgPath.toLowerCase();
|
|
860
|
-
let result = [];
|
|
861
|
-
/**
|
|
862
|
-
* hashtable to prevent duplicate results
|
|
863
|
-
*/
|
|
864
|
-
let resultPkgPaths = {};
|
|
865
|
-
//restrict to only .brs files
|
|
866
|
-
for (let key in this.files) {
|
|
867
|
-
let file = this.files[key];
|
|
868
|
-
if (
|
|
869
|
-
//is a BrightScript or BrighterScript file
|
|
870
|
-
(file.extension === '.bs' || file.extension === '.brs') &&
|
|
871
|
-
//this file is not the current file
|
|
872
|
-
lowerSourcePkgPath !== file.pkgPath.toLowerCase()) {
|
|
873
|
-
//add the relative path
|
|
874
|
-
let relativePath = util_1.util.getRelativePath(sourcePkgPath, file.pkgPath).replace(/\\/g, '/');
|
|
875
|
-
let pkgPathStandardized = file.pkgPath.replace(/\\/g, '/');
|
|
876
|
-
let filePkgPath = `pkg:/${pkgPathStandardized}`;
|
|
877
|
-
let lowerFilePkgPath = filePkgPath.toLowerCase();
|
|
878
|
-
if (!resultPkgPaths[lowerFilePkgPath]) {
|
|
879
|
-
resultPkgPaths[lowerFilePkgPath] = true;
|
|
880
|
-
result.push({
|
|
881
|
-
label: relativePath,
|
|
882
|
-
detail: file.srcPath,
|
|
883
|
-
kind: vscode_languageserver_1.CompletionItemKind.File,
|
|
884
|
-
textEdit: {
|
|
885
|
-
newText: relativePath,
|
|
886
|
-
range: scriptImport.filePathRange
|
|
887
|
-
}
|
|
888
|
-
});
|
|
889
|
-
//add the absolute path
|
|
890
|
-
result.push({
|
|
891
|
-
label: filePkgPath,
|
|
892
|
-
detail: file.srcPath,
|
|
893
|
-
kind: vscode_languageserver_1.CompletionItemKind.File,
|
|
894
|
-
textEdit: {
|
|
895
|
-
newText: filePkgPath,
|
|
896
|
-
range: scriptImport.filePathRange
|
|
897
|
-
}
|
|
898
|
-
});
|
|
899
|
-
}
|
|
900
|
-
}
|
|
1094
|
+
else {
|
|
1095
|
+
return null;
|
|
901
1096
|
}
|
|
902
|
-
return result;
|
|
903
1097
|
}
|
|
904
1098
|
/**
|
|
905
1099
|
* Transpile a single file and get the result as a string.
|
|
@@ -910,165 +1104,211 @@ class Program {
|
|
|
910
1104
|
* @param filePath can be a srcPath or a destPath
|
|
911
1105
|
*/
|
|
912
1106
|
async getTranspiledFileContents(filePath) {
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
1107
|
+
const file = this.getFile(filePath);
|
|
1108
|
+
return this.getTranspiledFileContentsPipeline.run(async () => {
|
|
1109
|
+
const result = {
|
|
1110
|
+
destPath: file.destPath,
|
|
1111
|
+
pkgPath: file.pkgPath,
|
|
1112
|
+
srcPath: file.srcPath
|
|
1113
|
+
};
|
|
1114
|
+
const expectedPkgPath = file.pkgPath.toLowerCase();
|
|
1115
|
+
const expectedMapPath = `${expectedPkgPath}.map`;
|
|
1116
|
+
const expectedTypedefPkgPath = expectedPkgPath.replace(/\.brs$/i, '.d.bs');
|
|
1117
|
+
//add a temporary plugin to tap into the file writing process
|
|
1118
|
+
const plugin = this.plugins.addFirst({
|
|
1119
|
+
name: 'getTranspiledFileContents',
|
|
1120
|
+
beforeWriteFile: (event) => {
|
|
1121
|
+
const pkgPath = event.file.pkgPath.toLowerCase();
|
|
1122
|
+
switch (pkgPath) {
|
|
1123
|
+
//this is the actual transpiled file
|
|
1124
|
+
case expectedPkgPath:
|
|
1125
|
+
result.code = event.file.data.toString();
|
|
1126
|
+
break;
|
|
1127
|
+
//this is the sourcemap
|
|
1128
|
+
case expectedMapPath:
|
|
1129
|
+
result.map = event.file.data.toString();
|
|
1130
|
+
break;
|
|
1131
|
+
//this is the typedef
|
|
1132
|
+
case expectedTypedefPkgPath:
|
|
1133
|
+
result.typedef = event.file.data.toString();
|
|
1134
|
+
break;
|
|
1135
|
+
default:
|
|
1136
|
+
//no idea what this file is. just ignore it
|
|
1137
|
+
}
|
|
1138
|
+
//mark every file as processed so it they don't get written to the output directory
|
|
1139
|
+
event.processedFiles.add(event.file);
|
|
1140
|
+
}
|
|
1141
|
+
});
|
|
1142
|
+
try {
|
|
1143
|
+
//now that the plugin has been registered, run the build with just this file
|
|
1144
|
+
await this.build({
|
|
1145
|
+
files: [file]
|
|
1146
|
+
});
|
|
919
1147
|
}
|
|
1148
|
+
finally {
|
|
1149
|
+
this.plugins.remove(plugin);
|
|
1150
|
+
}
|
|
1151
|
+
return result;
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
1154
|
+
/**
|
|
1155
|
+
* Get the absolute output path for a file
|
|
1156
|
+
*/
|
|
1157
|
+
getOutputPath(file, stagingDir = this.getStagingDir()) {
|
|
1158
|
+
return (0, util_1.standardizePath) `${stagingDir}/${file.pkgPath}`;
|
|
1159
|
+
}
|
|
1160
|
+
getStagingDir(stagingDir) {
|
|
1161
|
+
var _a, _b;
|
|
1162
|
+
let result = (_a = stagingDir !== null && stagingDir !== void 0 ? stagingDir : this.options.stagingDir) !== null && _a !== void 0 ? _a : this.options.stagingDir;
|
|
1163
|
+
if (!result) {
|
|
1164
|
+
result = roku_deploy_1.rokuDeploy.getOptions(this.options).stagingDir;
|
|
920
1165
|
}
|
|
921
|
-
|
|
922
|
-
const result = this._getTranspiledFileContents(this.getFile(filePath));
|
|
923
|
-
this.afterProgramTranspile(entries, astEditor);
|
|
1166
|
+
result = (0, util_1.standardizePath) `${path.resolve((_b = this.options.cwd) !== null && _b !== void 0 ? _b : process.cwd(), result !== null && result !== void 0 ? result : '/')}`;
|
|
924
1167
|
return result;
|
|
925
1168
|
}
|
|
926
1169
|
/**
|
|
927
|
-
*
|
|
928
|
-
*
|
|
1170
|
+
* Prepare the program for building
|
|
1171
|
+
* @param files the list of files that should be prepared
|
|
929
1172
|
*/
|
|
930
|
-
|
|
931
|
-
const
|
|
932
|
-
this.plugins.emit('beforeFileTranspile', {
|
|
1173
|
+
async prepare(files) {
|
|
1174
|
+
const programEvent = {
|
|
933
1175
|
program: this,
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
1176
|
+
editor: this.editor,
|
|
1177
|
+
files: files
|
|
1178
|
+
};
|
|
1179
|
+
//assign an editor to every file
|
|
1180
|
+
for (const file of files) {
|
|
1181
|
+
//if the file doesn't have an editor yet, assign one now
|
|
1182
|
+
if (!file.editor) {
|
|
1183
|
+
file.editor = new Editor_1.Editor();
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
files.sort((a, b) => {
|
|
1187
|
+
if (a.pkgPath < b.pkgPath) {
|
|
1188
|
+
return -1;
|
|
1189
|
+
}
|
|
1190
|
+
else if (a.pkgPath > b.pkgPath) {
|
|
1191
|
+
return 1;
|
|
1192
|
+
}
|
|
1193
|
+
else {
|
|
1194
|
+
return 1;
|
|
1195
|
+
}
|
|
937
1196
|
});
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1197
|
+
await this.plugins.emitAsync('beforePrepareProgram', programEvent);
|
|
1198
|
+
await this.plugins.emitAsync('prepareProgram', programEvent);
|
|
1199
|
+
const stagingDir = this.getStagingDir();
|
|
1200
|
+
const entries = [];
|
|
1201
|
+
for (const file of files) {
|
|
1202
|
+
//if the file doesn't have an editor yet, assign one now
|
|
1203
|
+
if (!file.editor) {
|
|
1204
|
+
file.editor = new Editor_1.Editor();
|
|
1205
|
+
}
|
|
1206
|
+
const event = {
|
|
1207
|
+
program: this,
|
|
1208
|
+
file: file,
|
|
1209
|
+
editor: file.editor,
|
|
1210
|
+
outputPath: this.getOutputPath(file, stagingDir)
|
|
1211
|
+
};
|
|
1212
|
+
await this.plugins.emitAsync('beforePrepareFile', event);
|
|
1213
|
+
await this.plugins.emitAsync('prepareFile', event);
|
|
1214
|
+
await this.plugins.emitAsync('afterPrepareFile', event);
|
|
1215
|
+
//TODO remove this in v1
|
|
1216
|
+
entries.push(event);
|
|
949
1217
|
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
file: file,
|
|
953
|
-
outputPath: outputPath,
|
|
954
|
-
editor: editor,
|
|
955
|
-
code: result.code,
|
|
956
|
-
map: result.map,
|
|
957
|
-
typedef: typedef
|
|
958
|
-
};
|
|
959
|
-
this.plugins.emit('afterFileTranspile', event);
|
|
960
|
-
//undo all `editor` edits that may have been applied to this file.
|
|
961
|
-
editor.undoAll();
|
|
962
|
-
return {
|
|
963
|
-
srcPath: file.srcPath,
|
|
964
|
-
pkgPath: file.pkgPath,
|
|
965
|
-
code: event.code,
|
|
966
|
-
map: event.map,
|
|
967
|
-
typedef: event.typedef
|
|
968
|
-
};
|
|
1218
|
+
await this.plugins.emitAsync('afterPrepareProgram', programEvent);
|
|
1219
|
+
return files;
|
|
969
1220
|
}
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
return {
|
|
1221
|
+
/**
|
|
1222
|
+
* Generate the contents of every file
|
|
1223
|
+
*/
|
|
1224
|
+
async serialize(files) {
|
|
1225
|
+
const allFiles = new Map();
|
|
1226
|
+
const serializeProgramEvent = await this.plugins.emitAsync('beforeSerializeProgram', {
|
|
1227
|
+
program: this,
|
|
1228
|
+
files: files,
|
|
1229
|
+
result: allFiles
|
|
1230
|
+
});
|
|
1231
|
+
await this.plugins.emitAsync('onSerializeProgram', {
|
|
1232
|
+
program: this,
|
|
1233
|
+
files: files,
|
|
1234
|
+
result: allFiles
|
|
1235
|
+
});
|
|
1236
|
+
//sort the entries to make transpiling more deterministic
|
|
1237
|
+
files = serializeProgramEvent.files.sort((a, b) => {
|
|
1238
|
+
return a.srcPath < b.srcPath ? -1 : 1;
|
|
1239
|
+
});
|
|
1240
|
+
// serialize each file
|
|
1241
|
+
for (const file of files) {
|
|
1242
|
+
const event = {
|
|
1243
|
+
program: this,
|
|
994
1244
|
file: file,
|
|
995
|
-
|
|
1245
|
+
result: allFiles
|
|
996
1246
|
};
|
|
1247
|
+
await this.plugins.emitAsync('beforeSerializeFile', event);
|
|
1248
|
+
await this.plugins.emitAsync('serializeFile', event);
|
|
1249
|
+
await this.plugins.emitAsync('afterSerializeFile', event);
|
|
1250
|
+
}
|
|
1251
|
+
this.plugins.emit('afterSerializeProgram', {
|
|
1252
|
+
program: this,
|
|
1253
|
+
files: files,
|
|
1254
|
+
result: allFiles
|
|
997
1255
|
});
|
|
998
|
-
|
|
999
|
-
|
|
1256
|
+
return allFiles;
|
|
1257
|
+
}
|
|
1258
|
+
/**
|
|
1259
|
+
* Write the entire project to disk
|
|
1260
|
+
*/
|
|
1261
|
+
async write(stagingDir, files) {
|
|
1262
|
+
const programEvent = await this.plugins.emitAsync('beforeWriteProgram', {
|
|
1000
1263
|
program: this,
|
|
1001
|
-
|
|
1002
|
-
|
|
1264
|
+
files: files,
|
|
1265
|
+
stagingDir: stagingDir
|
|
1003
1266
|
});
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1267
|
+
//empty the staging directory
|
|
1268
|
+
await fsExtra.emptyDir(stagingDir);
|
|
1269
|
+
const serializedFiles = [...files]
|
|
1270
|
+
.map(([, serializedFiles]) => serializedFiles)
|
|
1271
|
+
.flat();
|
|
1272
|
+
//write all the files to disk (asynchronously)
|
|
1273
|
+
await Promise.all(serializedFiles.map(async (file) => {
|
|
1274
|
+
const event = await this.plugins.emitAsync('beforeWriteFile', {
|
|
1275
|
+
program: this,
|
|
1276
|
+
file: file,
|
|
1277
|
+
outputPath: this.getOutputPath(file, stagingDir),
|
|
1278
|
+
processedFiles: new Set()
|
|
1279
|
+
});
|
|
1280
|
+
await this.plugins.emitAsync('writeFile', event);
|
|
1281
|
+
await this.plugins.emitAsync('afterWriteFile', event);
|
|
1282
|
+
}));
|
|
1283
|
+
await this.plugins.emitAsync('afterWriteProgram', programEvent);
|
|
1009
1284
|
}
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
processedFiles.add(outputPath === null || outputPath === void 0 ? void 0 : outputPath.toLowerCase());
|
|
1018
|
-
//skip transpiling typedef files
|
|
1019
|
-
if ((0, reflection_1.isBrsFile)(file) && file.isTypedef) {
|
|
1020
|
-
return;
|
|
1021
|
-
}
|
|
1022
|
-
const fileTranspileResult = this._getTranspiledFileContents(file, outputPath);
|
|
1023
|
-
//make sure the full dir path exists
|
|
1024
|
-
await fsExtra.ensureDir(path.dirname(outputPath));
|
|
1025
|
-
if (await fsExtra.pathExists(outputPath)) {
|
|
1026
|
-
throw new Error(`Error while transpiling "${file.srcPath}". A file already exists at "${outputPath}" and will not be overwritten.`);
|
|
1027
|
-
}
|
|
1028
|
-
const writeMapPromise = fileTranspileResult.map ? fsExtra.writeFile(`${outputPath}.map`, fileTranspileResult.map.toString()) : null;
|
|
1029
|
-
await Promise.all([
|
|
1030
|
-
fsExtra.writeFile(outputPath, fileTranspileResult.code),
|
|
1031
|
-
writeMapPromise
|
|
1032
|
-
]);
|
|
1033
|
-
if (fileTranspileResult.typedef) {
|
|
1034
|
-
const typedefPath = outputPath.replace(/\.brs$/i, '.d.bs');
|
|
1035
|
-
await fsExtra.writeFile(typedefPath, fileTranspileResult.typedef);
|
|
1036
|
-
}
|
|
1037
|
-
};
|
|
1038
|
-
let promises = entries.map(async (entry) => {
|
|
1285
|
+
/**
|
|
1286
|
+
* Build the project. This transpiles/transforms/copies all files and moves them to the staging directory
|
|
1287
|
+
* @param options the list of options used to build the program
|
|
1288
|
+
*/
|
|
1289
|
+
async build(options) {
|
|
1290
|
+
//run a single build at a time
|
|
1291
|
+
await this.buildPipeline.run(async () => {
|
|
1039
1292
|
var _a;
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
}
|
|
1058
|
-
if (promises.length > 0) {
|
|
1059
|
-
this.logger.info(`Transpiling ${promises.length} new files`);
|
|
1060
|
-
await Promise.all(promises);
|
|
1293
|
+
const stagingDir = this.getStagingDir(options === null || options === void 0 ? void 0 : options.stagingDir);
|
|
1294
|
+
const event = await this.plugins.emitAsync('beforeBuildProgram', {
|
|
1295
|
+
program: this,
|
|
1296
|
+
editor: this.editor,
|
|
1297
|
+
files: (_a = options === null || options === void 0 ? void 0 : options.files) !== null && _a !== void 0 ? _a : Object.values(this.files)
|
|
1298
|
+
});
|
|
1299
|
+
//prepare the program (and files) for building
|
|
1300
|
+
event.files = await this.prepare(event.files);
|
|
1301
|
+
//stage the entire program
|
|
1302
|
+
const serializedFilesByFile = await this.serialize(event.files);
|
|
1303
|
+
await this.write(stagingDir, serializedFilesByFile);
|
|
1304
|
+
await this.plugins.emitAsync('afterBuildProgram', event);
|
|
1305
|
+
//undo all edits for the program
|
|
1306
|
+
this.editor.undoAll();
|
|
1307
|
+
//undo all edits for each file
|
|
1308
|
+
for (const file of event.files) {
|
|
1309
|
+
file.editor.undoAll();
|
|
1061
1310
|
}
|
|
1062
|
-
} while (promises.length > 0);
|
|
1063
|
-
this.afterProgramTranspile(entries, astEditor);
|
|
1064
|
-
}
|
|
1065
|
-
afterProgramTranspile(entries, astEditor) {
|
|
1066
|
-
this.plugins.emit('afterProgramTranspile', {
|
|
1067
|
-
program: this,
|
|
1068
|
-
entries: entries,
|
|
1069
|
-
editor: astEditor
|
|
1070
1311
|
});
|
|
1071
|
-
astEditor.undoAll();
|
|
1072
1312
|
}
|
|
1073
1313
|
/**
|
|
1074
1314
|
* Find a list of files in the program that have a function with the given name (case INsensitive)
|
|
@@ -1139,36 +1379,84 @@ class Program {
|
|
|
1139
1379
|
}
|
|
1140
1380
|
return files;
|
|
1141
1381
|
}
|
|
1382
|
+
/**
|
|
1383
|
+
* Modify a parsed manifest map by reading `bs_const` and injecting values from `options.manifest.bs_const`
|
|
1384
|
+
* @param parsedManifest The manifest map to read from and modify
|
|
1385
|
+
*/
|
|
1386
|
+
buildBsConstsIntoParsedManifest(parsedManifest) {
|
|
1387
|
+
var _a, _b;
|
|
1388
|
+
// Lift the bs_consts defined in the manifest
|
|
1389
|
+
let bsConsts = (0, Manifest_1.getBsConst)(parsedManifest, false);
|
|
1390
|
+
// Override or delete any bs_consts defined in the bs config
|
|
1391
|
+
for (const key in (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.manifest) === null || _b === void 0 ? void 0 : _b.bs_const) {
|
|
1392
|
+
const value = this.options.manifest.bs_const[key];
|
|
1393
|
+
if (value === null) {
|
|
1394
|
+
bsConsts.delete(key);
|
|
1395
|
+
}
|
|
1396
|
+
else {
|
|
1397
|
+
bsConsts.set(key, value);
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
// convert the new list of bs consts back into a string for the rest of the down stream systems to use
|
|
1401
|
+
let constString = '';
|
|
1402
|
+
for (const [key, value] of bsConsts) {
|
|
1403
|
+
constString += `${constString !== '' ? ';' : ''}${key}=${value.toString()}`;
|
|
1404
|
+
}
|
|
1405
|
+
// Set the updated bs_const value
|
|
1406
|
+
parsedManifest.set('bs_const', constString);
|
|
1407
|
+
}
|
|
1408
|
+
/**
|
|
1409
|
+
* Try to find and load the manifest into memory
|
|
1410
|
+
* @param manifestFileObj A pointer to a potential manifest file object found during loading
|
|
1411
|
+
*/
|
|
1412
|
+
loadManifest(manifestFileObj) {
|
|
1413
|
+
let manifestPath = manifestFileObj
|
|
1414
|
+
? manifestFileObj.src
|
|
1415
|
+
: path.join(this.options.rootDir, 'manifest');
|
|
1416
|
+
try {
|
|
1417
|
+
// we only load this manifest once, so do it sync to improve speed downstream
|
|
1418
|
+
const contents = fsExtra.readFileSync(manifestPath, 'utf-8');
|
|
1419
|
+
const parsedManifest = (0, Manifest_1.parseManifest)(contents);
|
|
1420
|
+
this.buildBsConstsIntoParsedManifest(parsedManifest);
|
|
1421
|
+
this._manifest = parsedManifest;
|
|
1422
|
+
}
|
|
1423
|
+
catch (e) {
|
|
1424
|
+
this._manifest = new Map();
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1142
1427
|
/**
|
|
1143
1428
|
* Get a map of the manifest information
|
|
1144
1429
|
*/
|
|
1145
1430
|
getManifest() {
|
|
1146
1431
|
if (!this._manifest) {
|
|
1147
|
-
|
|
1148
|
-
//TODO update this to get the manifest from the files array or require it in the options...we shouldn't assume the location of the manifest
|
|
1149
|
-
let manifestPath = path.join(this.options.rootDir, 'manifest');
|
|
1150
|
-
let contents;
|
|
1151
|
-
try {
|
|
1152
|
-
//we only load this manifest once, so do it sync to improve speed downstream
|
|
1153
|
-
contents = fsExtra.readFileSync(manifestPath, 'utf-8');
|
|
1154
|
-
this._manifest = (0, Manifest_1.parseManifest)(contents);
|
|
1155
|
-
}
|
|
1156
|
-
catch (err) {
|
|
1157
|
-
this._manifest = new Map();
|
|
1158
|
-
}
|
|
1432
|
+
this.loadManifest();
|
|
1159
1433
|
}
|
|
1160
1434
|
return this._manifest;
|
|
1161
1435
|
}
|
|
1162
1436
|
dispose() {
|
|
1437
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1438
|
+
this.plugins.emit('beforeProgramDispose', { program: this });
|
|
1163
1439
|
for (let filePath in this.files) {
|
|
1164
|
-
this.files[filePath].dispose();
|
|
1440
|
+
(_b = (_a = this.files[filePath]) === null || _a === void 0 ? void 0 : _a.dispose) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
1165
1441
|
}
|
|
1166
1442
|
for (let name in this.scopes) {
|
|
1167
|
-
this.scopes[name].dispose();
|
|
1443
|
+
(_d = (_c = this.scopes[name]) === null || _c === void 0 ? void 0 : _c.dispose) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
1168
1444
|
}
|
|
1169
|
-
this.globalScope.dispose();
|
|
1170
|
-
this.dependencyGraph.dispose();
|
|
1445
|
+
(_f = (_e = this.globalScope) === null || _e === void 0 ? void 0 : _e.dispose) === null || _f === void 0 ? void 0 : _f.call(_e);
|
|
1446
|
+
(_h = (_g = this.dependencyGraph) === null || _g === void 0 ? void 0 : _g.dispose) === null || _h === void 0 ? void 0 : _h.call(_g);
|
|
1171
1447
|
}
|
|
1172
1448
|
}
|
|
1173
1449
|
exports.Program = Program;
|
|
1450
|
+
class ProvideFileEventInternal {
|
|
1451
|
+
constructor(program, srcPath, destPath, data, fileFactory) {
|
|
1452
|
+
var _a;
|
|
1453
|
+
this.program = program;
|
|
1454
|
+
this.srcPath = srcPath;
|
|
1455
|
+
this.destPath = destPath;
|
|
1456
|
+
this.data = data;
|
|
1457
|
+
this.fileFactory = fileFactory;
|
|
1458
|
+
this.files = [];
|
|
1459
|
+
this.srcExtension = (_a = path.extname(srcPath)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1174
1462
|
//# sourceMappingURL=Program.js.map
|