brighterscript 0.66.0-alpha.0 → 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 +223 -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 +656 -340
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.d.ts +10 -4
- package/dist/ProgramBuilder.js +83 -66
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +52 -49
- package/dist/Scope.js +312 -247
- package/dist/Scope.js.map +1 -1
- package/dist/SymbolTable.d.ts +35 -14
- package/dist/SymbolTable.js +89 -26
- 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 +11 -4
- package/dist/bscPlugin/BscPlugin.js +26 -6
- 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 +35 -65
- 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/ProgramValidator.d.ts +3 -3
- package/dist/bscPlugin/validation/ProgramValidator.js +6 -6
- package/dist/bscPlugin/validation/ProgramValidator.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 +63 -91
- 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 +436 -81
- 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);
|
|
127
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);
|
|
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,7 +223,6 @@ class Program {
|
|
|
153
223
|
}
|
|
154
224
|
addScope(scope) {
|
|
155
225
|
this.scopes[scope.name] = scope;
|
|
156
|
-
this.plugins.emit('afterScopeCreate', scope);
|
|
157
226
|
}
|
|
158
227
|
/**
|
|
159
228
|
* Get the component with the specified name
|
|
@@ -162,7 +231,7 @@ class Program {
|
|
|
162
231
|
var _a;
|
|
163
232
|
if (componentName) {
|
|
164
233
|
//return the first compoment in the list with this name
|
|
165
|
-
//(components are ordered in this list by
|
|
234
|
+
//(components are ordered in this list by destPath to ensure consistency)
|
|
166
235
|
return (_a = this.components[componentName.toLowerCase()]) === null || _a === void 0 ? void 0 : _a[0];
|
|
167
236
|
}
|
|
168
237
|
else {
|
|
@@ -173,8 +242,7 @@ class Program {
|
|
|
173
242
|
* Register (or replace) the reference to a component in the component map
|
|
174
243
|
*/
|
|
175
244
|
registerComponent(xmlFile, scope) {
|
|
176
|
-
|
|
177
|
-
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);
|
|
178
246
|
if (!this.components[key]) {
|
|
179
247
|
this.components[key] = [];
|
|
180
248
|
}
|
|
@@ -183,8 +251,8 @@ class Program {
|
|
|
183
251
|
scope: scope
|
|
184
252
|
});
|
|
185
253
|
this.components[key].sort((a, b) => {
|
|
186
|
-
const pathA = a.file.
|
|
187
|
-
const pathB = b.file.
|
|
254
|
+
const pathA = a.file.destPath.toLowerCase();
|
|
255
|
+
const pathB = b.file.destPath.toLowerCase();
|
|
188
256
|
if (pathA < pathB) {
|
|
189
257
|
return -1;
|
|
190
258
|
}
|
|
@@ -194,13 +262,13 @@ class Program {
|
|
|
194
262
|
return 0;
|
|
195
263
|
});
|
|
196
264
|
this.syncComponentDependencyGraph(this.components[key]);
|
|
265
|
+
this.addDeferredComponentTypeSymbolCreation(xmlFile);
|
|
197
266
|
}
|
|
198
267
|
/**
|
|
199
268
|
* Remove the specified component from the components map
|
|
200
269
|
*/
|
|
201
270
|
unregisterComponent(xmlFile) {
|
|
202
|
-
|
|
203
|
-
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);
|
|
204
272
|
const arr = this.components[key] || [];
|
|
205
273
|
for (let i = 0; i < arr.length; i++) {
|
|
206
274
|
if (arr[i].file === xmlFile) {
|
|
@@ -209,6 +277,44 @@ class Program {
|
|
|
209
277
|
}
|
|
210
278
|
}
|
|
211
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
|
+
}
|
|
212
318
|
}
|
|
213
319
|
/**
|
|
214
320
|
* re-attach the dependency graph with a new key for any component who changed
|
|
@@ -222,6 +328,7 @@ class Program {
|
|
|
222
328
|
//attach (or re-attach) the dependencyGraph for every component whose position changed
|
|
223
329
|
if (file.dependencyGraphIndex !== i) {
|
|
224
330
|
file.dependencyGraphIndex = i;
|
|
331
|
+
this.dependencyGraph.addOrReplace(file.dependencyGraphKey, file.dependencies);
|
|
225
332
|
file.attachDependencyGraph(this.dependencyGraph);
|
|
226
333
|
scope.attachDependencyGraph(this.dependencyGraph);
|
|
227
334
|
}
|
|
@@ -258,7 +365,7 @@ class Program {
|
|
|
258
365
|
//get the diagnostics from all unreferenced files
|
|
259
366
|
let unreferencedFiles = this.getUnreferencedFiles();
|
|
260
367
|
for (let file of unreferencedFiles) {
|
|
261
|
-
diagnostics.push(...file.
|
|
368
|
+
diagnostics.push(...file.diagnostics);
|
|
262
369
|
}
|
|
263
370
|
const filteredDiagnostics = this.logger.time(Logger_1.LogLevel.debug, ['filter diagnostics'], () => {
|
|
264
371
|
//filter out diagnostics based on our diagnostic filters
|
|
@@ -283,11 +390,9 @@ class Program {
|
|
|
283
390
|
hasFile(filePath, normalizePath = true) {
|
|
284
391
|
return !!this.getFile(filePath, normalizePath);
|
|
285
392
|
}
|
|
286
|
-
getPkgPath(...args) {
|
|
287
|
-
throw new Error('Not implemented');
|
|
288
|
-
}
|
|
289
393
|
/**
|
|
290
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"`
|
|
291
396
|
*/
|
|
292
397
|
getScopeByName(scopeName) {
|
|
293
398
|
if (!scopeName) {
|
|
@@ -295,8 +400,8 @@ class Program {
|
|
|
295
400
|
}
|
|
296
401
|
//most scopes are xml file pkg paths. however, the ones that are not are single names like "global" and "scope",
|
|
297
402
|
//so it's safe to run the standardizePkgPath method
|
|
298
|
-
scopeName = (0, util_1.standardizePath) `${scopeName}`;
|
|
299
|
-
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);
|
|
300
405
|
return this.scopes[key];
|
|
301
406
|
}
|
|
302
407
|
/**
|
|
@@ -316,8 +421,14 @@ class Program {
|
|
|
316
421
|
* Update internal maps with this file reference
|
|
317
422
|
*/
|
|
318
423
|
assignFile(file) {
|
|
424
|
+
const fileAddEvent = {
|
|
425
|
+
file: file,
|
|
426
|
+
program: this
|
|
427
|
+
};
|
|
428
|
+
this.plugins.emit('beforeFileAdd', fileAddEvent);
|
|
319
429
|
this.files[file.srcPath.toLowerCase()] = file;
|
|
320
|
-
this.
|
|
430
|
+
this.destMap.set(file.destPath.toLowerCase(), file);
|
|
431
|
+
this.plugins.emit('afterFileAdd', fileAddEvent);
|
|
321
432
|
return file;
|
|
322
433
|
}
|
|
323
434
|
/**
|
|
@@ -325,91 +436,102 @@ class Program {
|
|
|
325
436
|
*/
|
|
326
437
|
unassignFile(file) {
|
|
327
438
|
delete this.files[file.srcPath.toLowerCase()];
|
|
328
|
-
|
|
439
|
+
this.destMap.delete(file.destPath.toLowerCase());
|
|
329
440
|
return file;
|
|
330
441
|
}
|
|
331
|
-
setFile(fileParam,
|
|
442
|
+
setFile(fileParam, fileData) {
|
|
332
443
|
//normalize the file paths
|
|
333
|
-
const { srcPath,
|
|
444
|
+
const { srcPath, destPath } = this.getPaths(fileParam, this.options.rootDir);
|
|
334
445
|
let file = this.logger.time(Logger_1.LogLevel.debug, ['Program.setFile()', chalk_1.default.green(srcPath)], () => {
|
|
446
|
+
var _a, _b, _c;
|
|
335
447
|
//if the file is already loaded, remove it
|
|
336
448
|
if (this.hasFile(srcPath)) {
|
|
337
|
-
this.removeFile(srcPath);
|
|
449
|
+
this.removeFile(srcPath, true, true);
|
|
338
450
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
};
|
|
353
|
-
this.plugins.emit('beforeFileParse', sourceObj);
|
|
354
|
-
this.logger.time(Logger_1.LogLevel.debug, ['parse', chalk_1.default.green(srcPath)], () => {
|
|
355
|
-
brsFile.parse(sourceObj.source);
|
|
356
|
-
});
|
|
357
|
-
//notify plugins that this file has finished parsing
|
|
358
|
-
this.plugins.emit('afterFileParse', brsFile);
|
|
359
|
-
file = brsFile;
|
|
360
|
-
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
|
+
}));
|
|
361
464
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
srcPath: srcPath,
|
|
371
|
-
source: fileContents
|
|
372
|
-
};
|
|
373
|
-
this.plugins.emit('beforeFileParse', sourceObj);
|
|
374
|
-
this.logger.time(Logger_1.LogLevel.debug, ['parse', chalk_1.default.green(srcPath)], () => {
|
|
375
|
-
xmlFile.parse(sourceObj.source);
|
|
376
|
-
});
|
|
377
|
-
//notify plugins that this file has finished parsing
|
|
378
|
-
this.plugins.emit('afterFileParse', xmlFile);
|
|
379
|
-
file = xmlFile;
|
|
380
|
-
//create a new scope for this xml file
|
|
381
|
-
let scope = new XmlScope_1.XmlScope(xmlFile, this);
|
|
382
|
-
this.addScope(scope);
|
|
383
|
-
//register this compoent now that we have parsed it and know its component name
|
|
384
|
-
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
|
+
})))}`);
|
|
385
473
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
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
|
+
}
|
|
394
516
|
}
|
|
395
|
-
return
|
|
517
|
+
return primaryFile;
|
|
396
518
|
});
|
|
397
519
|
return file;
|
|
398
520
|
}
|
|
399
521
|
/**
|
|
400
|
-
* Given a srcPath, a
|
|
522
|
+
* Given a srcPath, a destPath, or both, resolve whichever is missing, relative to rootDir.
|
|
401
523
|
* @param fileParam an object representing file paths
|
|
402
524
|
* @param rootDir must be a pre-normalized path
|
|
403
525
|
*/
|
|
404
526
|
getPaths(fileParam, rootDir) {
|
|
405
527
|
let srcPath;
|
|
406
|
-
let
|
|
528
|
+
let destPath;
|
|
407
529
|
assert.ok(fileParam, 'fileParam is required');
|
|
408
|
-
//lift the
|
|
530
|
+
//lift the path vars from the incoming param
|
|
409
531
|
if (typeof fileParam === 'string') {
|
|
410
532
|
fileParam = this.removePkgPrefix(fileParam);
|
|
411
533
|
srcPath = (0, util_1.standardizePath) `${path.resolve(rootDir, fileParam)}`;
|
|
412
|
-
|
|
534
|
+
destPath = (0, util_1.standardizePath) `${util_1.util.replaceCaseInsensitive(srcPath, rootDir, '')}`;
|
|
413
535
|
}
|
|
414
536
|
else {
|
|
415
537
|
let param = fileParam;
|
|
@@ -420,30 +542,30 @@ class Program {
|
|
|
420
542
|
srcPath = (0, util_1.standardizePath) `${param.srcPath}`;
|
|
421
543
|
}
|
|
422
544
|
if (param.dest) {
|
|
423
|
-
|
|
545
|
+
destPath = (0, util_1.standardizePath) `${this.removePkgPrefix(param.dest)}`;
|
|
424
546
|
}
|
|
425
547
|
if (param.pkgPath) {
|
|
426
|
-
|
|
548
|
+
destPath = (0, util_1.standardizePath) `${this.removePkgPrefix(param.pkgPath)}`;
|
|
427
549
|
}
|
|
428
550
|
}
|
|
429
|
-
//if there's no srcPath, use the
|
|
551
|
+
//if there's no srcPath, use the destPath to build an absolute srcPath
|
|
430
552
|
if (!srcPath) {
|
|
431
|
-
srcPath = (0, util_1.standardizePath) `${rootDir}/${
|
|
553
|
+
srcPath = (0, util_1.standardizePath) `${rootDir}/${destPath}`;
|
|
432
554
|
}
|
|
433
555
|
//coerce srcPath to an absolute path
|
|
434
556
|
if (!path.isAbsolute(srcPath)) {
|
|
435
557
|
srcPath = util_1.util.standardizePath(srcPath);
|
|
436
558
|
}
|
|
437
|
-
//if
|
|
438
|
-
if (!
|
|
439
|
-
|
|
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, '')}`;
|
|
440
562
|
}
|
|
441
563
|
assert.ok(srcPath, 'fileEntry.src is required');
|
|
442
|
-
assert.ok(
|
|
564
|
+
assert.ok(destPath, 'fileEntry.dest is required');
|
|
443
565
|
return {
|
|
444
566
|
srcPath: srcPath,
|
|
445
|
-
//remove leading slash
|
|
446
|
-
|
|
567
|
+
//remove leading slash
|
|
568
|
+
destPath: destPath.replace(/^[\/\\]+/, '')
|
|
447
569
|
};
|
|
448
570
|
}
|
|
449
571
|
/**
|
|
@@ -452,6 +574,18 @@ class Program {
|
|
|
452
574
|
removePkgPrefix(path) {
|
|
453
575
|
return path.replace(/^pkg:\//i, '');
|
|
454
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
|
+
}
|
|
455
589
|
/**
|
|
456
590
|
* Ensure source scope is created.
|
|
457
591
|
* Note: automatically called internally, and no-op if it exists already.
|
|
@@ -461,6 +595,10 @@ class Program {
|
|
|
461
595
|
const sourceScope = new Scope_1.Scope('source', this, 'scope:source');
|
|
462
596
|
sourceScope.attachDependencyGraph(this.dependencyGraph);
|
|
463
597
|
this.addScope(sourceScope);
|
|
598
|
+
this.plugins.emit('afterScopeCreate', {
|
|
599
|
+
program: this,
|
|
600
|
+
scope: sourceScope
|
|
601
|
+
});
|
|
464
602
|
}
|
|
465
603
|
}
|
|
466
604
|
/**
|
|
@@ -475,38 +613,58 @@ class Program {
|
|
|
475
613
|
}
|
|
476
614
|
/**
|
|
477
615
|
* Remove a file from the program
|
|
478
|
-
* @param filePath can be a srcPath, a
|
|
616
|
+
* @param filePath can be a srcPath, a destPath, or a destPath with leading `pkg:/`
|
|
479
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
|
|
480
618
|
*/
|
|
481
|
-
removeFile(filePath, normalizePath = true) {
|
|
619
|
+
removeFile(filePath, normalizePath = true, keepSymbolInformation = false) {
|
|
620
|
+
var _a, _b, _c, _d;
|
|
482
621
|
this.logger.debug('Program.removeFile()', filePath);
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
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);
|
|
486
632
|
//if there is a scope named the same as this file's path, remove it (i.e. xml scopes)
|
|
487
|
-
let scope = this.scopes[file.
|
|
633
|
+
let scope = this.scopes[file.destPath];
|
|
488
634
|
if (scope) {
|
|
489
|
-
|
|
635
|
+
const scopeDisposeEvent = {
|
|
636
|
+
program: this,
|
|
637
|
+
scope: scope
|
|
638
|
+
};
|
|
639
|
+
this.plugins.emit('beforeScopeDispose', scopeDisposeEvent);
|
|
640
|
+
this.plugins.emit('onScopeDispose', scopeDisposeEvent);
|
|
490
641
|
scope.dispose();
|
|
491
642
|
//notify dependencies of this scope that it has been removed
|
|
492
643
|
this.dependencyGraph.remove(scope.dependencyGraphKey);
|
|
493
|
-
delete this.scopes[file.
|
|
494
|
-
this.plugins.emit('afterScopeDispose',
|
|
644
|
+
delete this.scopes[file.destPath];
|
|
645
|
+
this.plugins.emit('afterScopeDispose', scopeDisposeEvent);
|
|
495
646
|
}
|
|
496
647
|
//remove the file from the program
|
|
497
648
|
this.unassignFile(file);
|
|
498
649
|
this.dependencyGraph.remove(file.dependencyGraphKey);
|
|
499
650
|
//if this is a pkg:/source file, notify the `source` scope that it has changed
|
|
500
|
-
if (
|
|
651
|
+
if (this.isSourceBrsFile(file)) {
|
|
501
652
|
this.dependencyGraph.removeDependency('scope:source', file.dependencyGraphKey);
|
|
653
|
+
if (!keepSymbolInformation) {
|
|
654
|
+
this.fileSymbolInformation.delete(file.pkgPath);
|
|
655
|
+
}
|
|
502
656
|
}
|
|
503
657
|
//if this is a component, remove it from our components map
|
|
504
658
|
if ((0, reflection_1.isXmlFile)(file)) {
|
|
505
659
|
this.unregisterComponent(file);
|
|
506
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
|
+
}
|
|
507
665
|
//dispose file
|
|
508
|
-
file === null || file === void 0 ? void 0 : file.dispose();
|
|
509
|
-
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);
|
|
510
668
|
}
|
|
511
669
|
}
|
|
512
670
|
/**
|
|
@@ -514,37 +672,138 @@ class Program {
|
|
|
514
672
|
*/
|
|
515
673
|
validate() {
|
|
516
674
|
this.logger.time(Logger_1.LogLevel.log, ['Validating project'], () => {
|
|
675
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
517
676
|
this.diagnostics = [];
|
|
518
|
-
|
|
677
|
+
const programValidateEvent = {
|
|
678
|
+
program: this
|
|
679
|
+
};
|
|
680
|
+
this.plugins.emit('beforeProgramValidate', programValidateEvent);
|
|
681
|
+
this.plugins.emit('onProgramValidate', programValidateEvent);
|
|
519
682
|
//validate every file
|
|
683
|
+
const brsFilesValidated = [];
|
|
520
684
|
for (const file of Object.values(this.files)) {
|
|
521
685
|
//for every unvalidated file, validate it
|
|
522
686
|
if (!file.isValidated) {
|
|
523
|
-
|
|
687
|
+
const validateFileEvent = {
|
|
524
688
|
program: this,
|
|
525
689
|
file: file
|
|
526
|
-
}
|
|
690
|
+
};
|
|
691
|
+
this.plugins.emit('beforeFileValidate', validateFileEvent);
|
|
527
692
|
//emit an event to allow plugins to contribute to the file validation process
|
|
528
|
-
this.plugins.emit('onFileValidate',
|
|
529
|
-
program: this,
|
|
530
|
-
file: file
|
|
531
|
-
});
|
|
693
|
+
this.plugins.emit('onFileValidate', validateFileEvent);
|
|
532
694
|
file.isValidated = true;
|
|
533
|
-
|
|
695
|
+
if ((0, reflection_1.isBrsFile)(file)) {
|
|
696
|
+
brsFilesValidated.push(file);
|
|
697
|
+
}
|
|
698
|
+
this.plugins.emit('afterFileValidate', validateFileEvent);
|
|
699
|
+
}
|
|
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;
|
|
534
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));
|
|
535
786
|
}
|
|
536
787
|
this.logger.time(Logger_1.LogLevel.info, ['Validate all scopes'], () => {
|
|
537
788
|
for (let scopeName in this.scopes) {
|
|
538
789
|
let scope = this.scopes[scopeName];
|
|
539
|
-
scope.
|
|
540
|
-
scope.validate();
|
|
541
|
-
scope.unlinkSymbolTable();
|
|
790
|
+
scope.validate({ changedFiles: brsFilesValidated, changedSymbols: changedSymbols });
|
|
542
791
|
}
|
|
543
792
|
});
|
|
544
793
|
this.detectDuplicateComponentNames();
|
|
545
|
-
this.plugins.emit('afterProgramValidate',
|
|
794
|
+
this.plugins.emit('afterProgramValidate', programValidateEvent);
|
|
546
795
|
});
|
|
547
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
|
+
}
|
|
548
807
|
/**
|
|
549
808
|
* Flag all duplicate component names
|
|
550
809
|
*/
|
|
@@ -597,12 +856,13 @@ class Program {
|
|
|
597
856
|
getFile(filePath, normalizePath = true) {
|
|
598
857
|
if (typeof filePath !== 'string') {
|
|
599
858
|
return undefined;
|
|
859
|
+
//is the path absolute (or the `virtual:` prefix)
|
|
600
860
|
}
|
|
601
|
-
else if (
|
|
861
|
+
else if (/^(?:(?:virtual:[\/\\])|(?:\w:)|(?:[\/\\]))/gmi.exec(filePath)) {
|
|
602
862
|
return this.files[(normalizePath ? util_1.util.standardizePath(filePath) : filePath).toLowerCase()];
|
|
603
863
|
}
|
|
604
864
|
else {
|
|
605
|
-
return this.
|
|
865
|
+
return this.destMap.get((normalizePath ? util_1.util.standardizePath(filePath) : filePath).toLowerCase());
|
|
606
866
|
}
|
|
607
867
|
}
|
|
608
868
|
/**
|
|
@@ -644,7 +904,8 @@ class Program {
|
|
|
644
904
|
//look through all files in scope for matches
|
|
645
905
|
for (const scope of this.getScopesForFile(originFile)) {
|
|
646
906
|
for (const file of scope.getAllFiles()) {
|
|
647
|
-
|
|
907
|
+
//skip non-brs files, or files we've already processed
|
|
908
|
+
if (!(0, reflection_1.isBrsFile)(file) || filesSearched.has(file)) {
|
|
648
909
|
continue;
|
|
649
910
|
}
|
|
650
911
|
filesSearched.add(file);
|
|
@@ -677,7 +938,8 @@ class Program {
|
|
|
677
938
|
}
|
|
678
939
|
//look through all files in scope for matches
|
|
679
940
|
for (const file of scope.getOwnFiles()) {
|
|
680
|
-
|
|
941
|
+
//skip non-brs files, or files we've already processed
|
|
942
|
+
if (!(0, reflection_1.isBrsFile)(file) || filesSearched.has(file)) {
|
|
681
943
|
continue;
|
|
682
944
|
}
|
|
683
945
|
filesSearched.add(file);
|
|
@@ -826,60 +1088,12 @@ class Program {
|
|
|
826
1088
|
getReferences(srcPath, position) {
|
|
827
1089
|
//find the file
|
|
828
1090
|
let file = this.getFile(srcPath);
|
|
829
|
-
if (
|
|
830
|
-
return
|
|
1091
|
+
if ((0, reflection_1.isBrsFile)(file) || (0, reflection_1.isXmlFile)(file)) {
|
|
1092
|
+
return file.getReferences(position);
|
|
831
1093
|
}
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
/**
|
|
835
|
-
* Get a list of all script imports, relative to the specified pkgPath
|
|
836
|
-
* @param sourcePkgPath - the pkgPath of the source that wants to resolve script imports.
|
|
837
|
-
*/
|
|
838
|
-
getScriptImportCompletions(sourcePkgPath, scriptImport) {
|
|
839
|
-
let lowerSourcePkgPath = sourcePkgPath.toLowerCase();
|
|
840
|
-
let result = [];
|
|
841
|
-
/**
|
|
842
|
-
* hashtable to prevent duplicate results
|
|
843
|
-
*/
|
|
844
|
-
let resultPkgPaths = {};
|
|
845
|
-
//restrict to only .brs files
|
|
846
|
-
for (let key in this.files) {
|
|
847
|
-
let file = this.files[key];
|
|
848
|
-
if (
|
|
849
|
-
//is a BrightScript or BrighterScript file
|
|
850
|
-
(file.extension === '.bs' || file.extension === '.brs') &&
|
|
851
|
-
//this file is not the current file
|
|
852
|
-
lowerSourcePkgPath !== file.pkgPath.toLowerCase()) {
|
|
853
|
-
//add the relative path
|
|
854
|
-
let relativePath = util_1.util.getRelativePath(sourcePkgPath, file.pkgPath).replace(/\\/g, '/');
|
|
855
|
-
let pkgPathStandardized = file.pkgPath.replace(/\\/g, '/');
|
|
856
|
-
let filePkgPath = `pkg:/${pkgPathStandardized}`;
|
|
857
|
-
let lowerFilePkgPath = filePkgPath.toLowerCase();
|
|
858
|
-
if (!resultPkgPaths[lowerFilePkgPath]) {
|
|
859
|
-
resultPkgPaths[lowerFilePkgPath] = true;
|
|
860
|
-
result.push({
|
|
861
|
-
label: relativePath,
|
|
862
|
-
detail: file.srcPath,
|
|
863
|
-
kind: vscode_languageserver_1.CompletionItemKind.File,
|
|
864
|
-
textEdit: {
|
|
865
|
-
newText: relativePath,
|
|
866
|
-
range: scriptImport.filePathRange
|
|
867
|
-
}
|
|
868
|
-
});
|
|
869
|
-
//add the absolute path
|
|
870
|
-
result.push({
|
|
871
|
-
label: filePkgPath,
|
|
872
|
-
detail: file.srcPath,
|
|
873
|
-
kind: vscode_languageserver_1.CompletionItemKind.File,
|
|
874
|
-
textEdit: {
|
|
875
|
-
newText: filePkgPath,
|
|
876
|
-
range: scriptImport.filePathRange
|
|
877
|
-
}
|
|
878
|
-
});
|
|
879
|
-
}
|
|
880
|
-
}
|
|
1094
|
+
else {
|
|
1095
|
+
return null;
|
|
881
1096
|
}
|
|
882
|
-
return result;
|
|
883
1097
|
}
|
|
884
1098
|
/**
|
|
885
1099
|
* Transpile a single file and get the result as a string.
|
|
@@ -890,157 +1104,211 @@ class Program {
|
|
|
890
1104
|
* @param filePath can be a srcPath or a destPath
|
|
891
1105
|
*/
|
|
892
1106
|
async getTranspiledFileContents(filePath) {
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
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
|
+
});
|
|
1147
|
+
}
|
|
1148
|
+
finally {
|
|
1149
|
+
this.plugins.remove(plugin);
|
|
899
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;
|
|
900
1165
|
}
|
|
901
|
-
|
|
902
|
-
const result = this._getTranspiledFileContents(this.getFile(filePath));
|
|
903
|
-
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 : '/')}`;
|
|
904
1167
|
return result;
|
|
905
1168
|
}
|
|
906
1169
|
/**
|
|
907
|
-
*
|
|
908
|
-
*
|
|
1170
|
+
* Prepare the program for building
|
|
1171
|
+
* @param files the list of files that should be prepared
|
|
909
1172
|
*/
|
|
910
|
-
|
|
911
|
-
const
|
|
912
|
-
this.plugins.emit('beforeFileTranspile', {
|
|
1173
|
+
async prepare(files) {
|
|
1174
|
+
const programEvent = {
|
|
913
1175
|
program: this,
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
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
|
+
}
|
|
917
1196
|
});
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
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);
|
|
929
1217
|
}
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
file: file,
|
|
933
|
-
outputPath: outputPath,
|
|
934
|
-
editor: editor,
|
|
935
|
-
code: result.code,
|
|
936
|
-
map: result.map,
|
|
937
|
-
typedef: typedef
|
|
938
|
-
};
|
|
939
|
-
this.plugins.emit('afterFileTranspile', event);
|
|
940
|
-
//undo all `editor` edits that may have been applied to this file.
|
|
941
|
-
editor.undoAll();
|
|
942
|
-
return {
|
|
943
|
-
srcPath: file.srcPath,
|
|
944
|
-
pkgPath: file.pkgPath,
|
|
945
|
-
code: event.code,
|
|
946
|
-
map: event.map,
|
|
947
|
-
typedef: event.typedef
|
|
948
|
-
};
|
|
1218
|
+
await this.plugins.emitAsync('afterPrepareProgram', programEvent);
|
|
1219
|
+
return files;
|
|
949
1220
|
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
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,
|
|
974
1244
|
file: file,
|
|
975
|
-
|
|
1245
|
+
result: allFiles
|
|
976
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
|
|
977
1255
|
});
|
|
978
|
-
|
|
979
|
-
this.plugins.emit('beforeProgramTranspile', this, entries, astEditor);
|
|
980
|
-
return {
|
|
981
|
-
entries: entries,
|
|
982
|
-
getOutputPath: getOutputPath,
|
|
983
|
-
astEditor: astEditor
|
|
984
|
-
};
|
|
1256
|
+
return allFiles;
|
|
985
1257
|
}
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
//skip transpiling typedef files
|
|
995
|
-
if ((0, reflection_1.isBrsFile)(file) && file.isTypedef) {
|
|
996
|
-
return;
|
|
997
|
-
}
|
|
998
|
-
const fileTranspileResult = this._getTranspiledFileContents(file, outputPath);
|
|
999
|
-
//make sure the full dir path exists
|
|
1000
|
-
await fsExtra.ensureDir(path.dirname(outputPath));
|
|
1001
|
-
if (await fsExtra.pathExists(outputPath)) {
|
|
1002
|
-
throw new Error(`Error while transpiling "${file.srcPath}". A file already exists at "${outputPath}" and will not be overwritten.`);
|
|
1003
|
-
}
|
|
1004
|
-
const writeMapPromise = fileTranspileResult.map ? fsExtra.writeFile(`${outputPath}.map`, fileTranspileResult.map.toString()) : null;
|
|
1005
|
-
await Promise.all([
|
|
1006
|
-
fsExtra.writeFile(outputPath, fileTranspileResult.code),
|
|
1007
|
-
writeMapPromise
|
|
1008
|
-
]);
|
|
1009
|
-
if (fileTranspileResult.typedef) {
|
|
1010
|
-
const typedefPath = outputPath.replace(/\.brs$/i, '.d.bs');
|
|
1011
|
-
await fsExtra.writeFile(typedefPath, fileTranspileResult.typedef);
|
|
1012
|
-
}
|
|
1013
|
-
};
|
|
1014
|
-
let promises = entries.map(async (entry) => {
|
|
1015
|
-
var _a;
|
|
1016
|
-
return transpileFile((_a = entry === null || entry === void 0 ? void 0 : entry.file) === null || _a === void 0 ? void 0 : _a.srcPath, entry.outputPath);
|
|
1258
|
+
/**
|
|
1259
|
+
* Write the entire project to disk
|
|
1260
|
+
*/
|
|
1261
|
+
async write(stagingDir, files) {
|
|
1262
|
+
const programEvent = await this.plugins.emitAsync('beforeWriteProgram', {
|
|
1263
|
+
program: this,
|
|
1264
|
+
files: files,
|
|
1265
|
+
stagingDir: stagingDir
|
|
1017
1266
|
});
|
|
1018
|
-
//
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
//
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
this.logger.info(`Transpiling ${promises.length} new files`);
|
|
1036
|
-
await Promise.all(promises);
|
|
1037
|
-
}
|
|
1038
|
-
} while (promises.length > 0);
|
|
1039
|
-
this.afterProgramTranspile(entries, astEditor);
|
|
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);
|
|
1040
1284
|
}
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
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 () => {
|
|
1292
|
+
var _a;
|
|
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();
|
|
1310
|
+
}
|
|
1311
|
+
});
|
|
1044
1312
|
}
|
|
1045
1313
|
/**
|
|
1046
1314
|
* Find a list of files in the program that have a function with the given name (case INsensitive)
|
|
@@ -1111,36 +1379,84 @@ class Program {
|
|
|
1111
1379
|
}
|
|
1112
1380
|
return files;
|
|
1113
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
|
+
}
|
|
1114
1427
|
/**
|
|
1115
1428
|
* Get a map of the manifest information
|
|
1116
1429
|
*/
|
|
1117
1430
|
getManifest() {
|
|
1118
1431
|
if (!this._manifest) {
|
|
1119
|
-
|
|
1120
|
-
//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
|
|
1121
|
-
let manifestPath = path.join(this.options.rootDir, 'manifest');
|
|
1122
|
-
let contents;
|
|
1123
|
-
try {
|
|
1124
|
-
//we only load this manifest once, so do it sync to improve speed downstream
|
|
1125
|
-
contents = fsExtra.readFileSync(manifestPath, 'utf-8');
|
|
1126
|
-
this._manifest = (0, Manifest_1.parseManifest)(contents);
|
|
1127
|
-
}
|
|
1128
|
-
catch (err) {
|
|
1129
|
-
this._manifest = new Map();
|
|
1130
|
-
}
|
|
1432
|
+
this.loadManifest();
|
|
1131
1433
|
}
|
|
1132
1434
|
return this._manifest;
|
|
1133
1435
|
}
|
|
1134
1436
|
dispose() {
|
|
1437
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1438
|
+
this.plugins.emit('beforeProgramDispose', { program: this });
|
|
1135
1439
|
for (let filePath in this.files) {
|
|
1136
|
-
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);
|
|
1137
1441
|
}
|
|
1138
1442
|
for (let name in this.scopes) {
|
|
1139
|
-
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);
|
|
1140
1444
|
}
|
|
1141
|
-
this.globalScope.dispose();
|
|
1142
|
-
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);
|
|
1143
1447
|
}
|
|
1144
1448
|
}
|
|
1145
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
|
+
}
|
|
1146
1462
|
//# sourceMappingURL=Program.js.map
|