brighterscript 0.66.0-alpha.5 → 0.66.0-alpha.7
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 +64 -10
- package/README.md +16 -0
- 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/BsConfig.d.ts +15 -1
- package/dist/CommentFlagProcessor.d.ts +4 -3
- package/dist/CommentFlagProcessor.js.map +1 -1
- package/dist/DiagnosticMessages.d.ts +19 -4
- package/dist/DiagnosticMessages.js +45 -5
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/LanguageServer.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 +101 -37
- package/dist/Program.js +492 -274
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.d.ts +10 -4
- package/dist/ProgramBuilder.js +44 -54
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +27 -13
- package/dist/Scope.js +44 -26
- package/dist/Scope.js.map +1 -1
- package/dist/SymbolTable.d.ts +5 -0
- package/dist/SymbolTable.js +15 -2
- package/dist/SymbolTable.js.map +1 -1
- package/dist/XmlScope.d.ts +7 -4
- package/dist/XmlScope.js +47 -8
- 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 +9 -1
- package/dist/astUtils/creators.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +30 -8
- package/dist/astUtils/reflection.js +64 -14
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/reflection.spec.js +85 -4
- package/dist/astUtils/reflection.spec.js.map +1 -1
- package/dist/astUtils/visitors.d.ts +3 -3
- package/dist/astUtils/visitors.spec.js +7 -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/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 +11 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.js +112 -58
- package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +151 -6
- package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -1
- 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 +1 -7
- package/dist/bscPlugin/hover/HoverProcessor.js +2 -8
- package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -1
- package/dist/bscPlugin/hover/HoverProcessor.spec.js +55 -0
- 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} +25 -4
- 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.js +2 -1
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
- package/dist/bscPlugin/validation/ScopeValidator.d.ts +12 -0
- package/dist/bscPlugin/validation/ScopeValidator.js +137 -19
- package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
- package/dist/bscPlugin/validation/ScopeValidator.spec.js +671 -1
- package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -1
- package/dist/bscPlugin/validation/XmlFileValidator.js +2 -2
- package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -1
- package/dist/cli.js +1 -0
- package/dist/cli.js.map +1 -1
- package/dist/deferred.d.ts +2 -2
- package/dist/deferred.js.map +1 -1
- package/dist/diagnosticUtils.d.ts +1 -0
- package/dist/diagnosticUtils.js +4 -3
- 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 +40 -40
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +42 -15
- package/dist/files/BrsFile.js +120 -78
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +266 -167
- 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 +55 -17
- package/dist/files/XmlFile.js +88 -47
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/XmlFile.spec.js +64 -57
- 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 +2 -6
- package/dist/globalCallables.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +326 -85
- package/dist/interfaces.js +4 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/lexer/Lexer.js +1 -1
- package/dist/lexer/TokenKind.js +0 -1
- package/dist/lexer/TokenKind.js.map +1 -1
- package/dist/parser/AstNode.d.ts +2 -2
- package/dist/parser/AstNode.js +1 -1
- 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 +1 -1
- package/dist/parser/Expression.js +35 -19
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.js +12 -1
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.js +18 -2
- package/dist/parser/Parser.spec.js.map +1 -1
- package/dist/parser/SGParser.d.ts +2 -2
- 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 +1 -1
- package/dist/parser/Statement.js +1 -1
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +10 -10
- 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 +64 -36
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +34 -34
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
- package/dist/parser/tests/statement/ConstStatement.spec.js +17 -17
- 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 +26 -26
- 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 +18 -10
- package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/PrintStatement.spec.js +10 -10
- package/dist/parser/tests/statement/PrintStatement.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 +111 -149
- package/dist/roku-types/index.d.ts +27 -13
- package/dist/types/ArrayType.d.ts +2 -1
- package/dist/types/ArrayType.js +6 -2
- package/dist/types/ArrayType.js.map +1 -1
- package/dist/types/ArrayType.spec.js +11 -1
- 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 +2 -1
- package/dist/types/BaseFunctionType.js +1 -1
- package/dist/types/BaseFunctionType.js.map +1 -1
- package/dist/types/BooleanType.d.ts +2 -1
- package/dist/types/BooleanType.js +3 -2
- package/dist/types/BooleanType.js.map +1 -1
- package/dist/types/BscType.d.ts +3 -3
- package/dist/types/BscType.js +26 -12
- package/dist/types/BscType.js.map +1 -1
- package/dist/types/BscTypeKind.d.ts +2 -0
- package/dist/types/BscTypeKind.js +2 -0
- package/dist/types/BscTypeKind.js.map +1 -1
- package/dist/types/BuiltInInterfaceAdder.d.ts +8 -0
- package/dist/types/BuiltInInterfaceAdder.js +88 -23
- package/dist/types/BuiltInInterfaceAdder.js.map +1 -1
- package/dist/types/ClassType.d.ts +2 -1
- package/dist/types/ClassType.js +2 -2
- package/dist/types/ClassType.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 +4 -2
- package/dist/types/DoubleType.js.map +1 -1
- package/dist/types/DynamicType.d.ts +2 -2
- package/dist/types/DynamicType.js +1 -1
- package/dist/types/DynamicType.js.map +1 -1
- package/dist/types/EnumType.d.ts +3 -2
- package/dist/types/EnumType.js +3 -3
- package/dist/types/EnumType.js.map +1 -1
- package/dist/types/FloatType.d.ts +2 -1
- package/dist/types/FloatType.js +4 -2
- package/dist/types/FloatType.js.map +1 -1
- package/dist/types/FunctionType.d.ts +2 -1
- package/dist/types/FunctionType.js +2 -2
- package/dist/types/FunctionType.js.map +1 -1
- package/dist/types/IntegerType.d.ts +2 -1
- package/dist/types/IntegerType.js +4 -2
- package/dist/types/IntegerType.js.map +1 -1
- package/dist/types/InterfaceType.d.ts +2 -1
- package/dist/types/InterfaceType.js +3 -7
- package/dist/types/InterfaceType.js.map +1 -1
- package/dist/types/InterfaceType.spec.js +25 -2
- package/dist/types/InterfaceType.spec.js.map +1 -1
- package/dist/types/LongIntegerType.d.ts +2 -1
- package/dist/types/LongIntegerType.js +4 -2
- package/dist/types/LongIntegerType.js.map +1 -1
- package/dist/types/ObjectType.d.ts +2 -2
- package/dist/types/ObjectType.js +1 -1
- package/dist/types/ObjectType.js.map +1 -1
- package/dist/types/ReferenceType.d.ts +2 -0
- package/dist/types/ReferenceType.js +45 -1
- package/dist/types/ReferenceType.js.map +1 -1
- package/dist/types/StringType.d.ts +2 -1
- package/dist/types/StringType.js +4 -4
- package/dist/types/StringType.js.map +1 -1
- package/dist/types/TypedFunctionType.d.ts +7 -1
- package/dist/types/TypedFunctionType.js +47 -17
- package/dist/types/TypedFunctionType.js.map +1 -1
- package/dist/types/TypedFunctionType.spec.js +99 -0
- package/dist/types/TypedFunctionType.spec.js.map +1 -1
- 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 +2 -2
- package/dist/types/UnionType.js +10 -3
- package/dist/types/UnionType.js.map +1 -1
- package/dist/types/UnionType.spec.js +3 -2
- package/dist/types/UnionType.spec.js.map +1 -1
- package/dist/types/VoidType.d.ts +2 -1
- package/dist/types/VoidType.js +2 -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 -1
- package/dist/types/helpers.js +31 -3
- package/dist/types/helpers.js.map +1 -1
- package/dist/util.d.ts +26 -6
- package/dist/util.js +181 -52
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +1 -1
- 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/astUtils/{AstEditor.spec.d.ts → Editor.spec.d.ts} +0 -0
- /package/dist/bscPlugin/{transpile/BrsFilePreTranspileProcessor.spec.d.ts → serialize/BslibInjector.spec.d.ts} +0 -0
package/dist/Program.js
CHANGED
|
@@ -6,8 +6,6 @@ const fsExtra = require("fs-extra");
|
|
|
6
6
|
const path = require("path");
|
|
7
7
|
const Scope_1 = require("./Scope");
|
|
8
8
|
const DiagnosticMessages_1 = require("./DiagnosticMessages");
|
|
9
|
-
const BrsFile_1 = require("./files/BrsFile");
|
|
10
|
-
const XmlFile_1 = require("./files/XmlFile");
|
|
11
9
|
const util_1 = require("./util");
|
|
12
10
|
const XmlScope_1 = require("./XmlScope");
|
|
13
11
|
const DiagnosticFilterer_1 = require("./DiagnosticFilterer");
|
|
@@ -20,8 +18,7 @@ const vscode_uri_1 = require("vscode-uri");
|
|
|
20
18
|
const PluginInterface_1 = require("./PluginInterface");
|
|
21
19
|
const reflection_1 = require("./astUtils/reflection");
|
|
22
20
|
const BscPlugin_1 = require("./bscPlugin/BscPlugin");
|
|
23
|
-
const
|
|
24
|
-
const roku_deploy_1 = require("roku-deploy");
|
|
21
|
+
const Editor_1 = require("./astUtils/Editor");
|
|
25
22
|
const CallExpressionInfo_1 = require("./bscPlugin/CallExpressionInfo");
|
|
26
23
|
const SignatureHelpUtil_1 = require("./bscPlugin/SignatureHelpUtil");
|
|
27
24
|
const DiagnosticSeverityAdjuster_1 = require("./DiagnosticSeverityAdjuster");
|
|
@@ -36,7 +33,14 @@ const LongIntegerType_1 = require("./types/LongIntegerType");
|
|
|
36
33
|
const ObjectType_1 = require("./types/ObjectType");
|
|
37
34
|
const VoidType_1 = require("./types/VoidType");
|
|
38
35
|
const FunctionType_1 = require("./types/FunctionType");
|
|
39
|
-
const
|
|
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");
|
|
40
44
|
const bslibNonAliasedRokuModulesPkgPath = (0, util_1.standardizePath) `source/roku_modules/rokucommunity_bslib/bslib.brs`;
|
|
41
45
|
const bslibAliasedRokuModulesPkgPath = (0, util_1.standardizePath) `source/roku_modules/bslib/bslib.brs`;
|
|
42
46
|
class Program {
|
|
@@ -46,6 +50,10 @@ class Program {
|
|
|
46
50
|
*/
|
|
47
51
|
options, logger, plugins) {
|
|
48
52
|
this.options = options;
|
|
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();
|
|
49
57
|
/**
|
|
50
58
|
* A graph of all files and their dependencies.
|
|
51
59
|
* For example:
|
|
@@ -64,7 +72,16 @@ class Program {
|
|
|
64
72
|
* A map of every file loaded into this program, indexed by its original file location
|
|
65
73
|
*/
|
|
66
74
|
this.files = {};
|
|
67
|
-
|
|
75
|
+
/**
|
|
76
|
+
* A map of every file loaded into this program, indexed by its destPath
|
|
77
|
+
*/
|
|
78
|
+
this.destMap = new Map();
|
|
79
|
+
/**
|
|
80
|
+
* Plugins can contribute multiple virtual files for a single physical file.
|
|
81
|
+
* This collection links the virtual files back to the physical file that produced them.
|
|
82
|
+
* The key is the standardized and lower-cased srcPath
|
|
83
|
+
*/
|
|
84
|
+
this.fileClusters = new Map();
|
|
68
85
|
this.scopes = {};
|
|
69
86
|
/**
|
|
70
87
|
* A map of every component currently loaded into the program, indexed by the component name.
|
|
@@ -73,6 +90,12 @@ class Program {
|
|
|
73
90
|
* but if you do, only ever use the component at index 0.
|
|
74
91
|
*/
|
|
75
92
|
this.components = {};
|
|
93
|
+
/**
|
|
94
|
+
* Keeps a set of all the components that need to have their types updated during the current validation cycle
|
|
95
|
+
*/
|
|
96
|
+
this.componentSymbolsToUpdate = new Set();
|
|
97
|
+
this.getTranspiledFileContentsPipeline = new ActionPipeline_1.ActionPipeline();
|
|
98
|
+
this.buildPipeline = new ActionPipeline_1.ActionPipeline();
|
|
76
99
|
this.options = util_1.util.normalizeConfig(options);
|
|
77
100
|
this.logger = logger || new Logger_1.Logger(options.logLevel);
|
|
78
101
|
this.plugins = plugins || new PluginInterface_1.default([], { logger: this.logger });
|
|
@@ -81,6 +104,7 @@ class Program {
|
|
|
81
104
|
//normalize the root dir path
|
|
82
105
|
this.options.rootDir = util_1.util.getRootDir(this.options);
|
|
83
106
|
this.createGlobalScope();
|
|
107
|
+
this.fileFactory = new Factory_1.FileFactory(this);
|
|
84
108
|
}
|
|
85
109
|
createGlobalScope() {
|
|
86
110
|
//create the 'global' scope
|
|
@@ -96,12 +120,37 @@ class Program {
|
|
|
96
120
|
//TODO we might need to fix this because the isValidated clears stuff now
|
|
97
121
|
this.globalScope.isValidated = true;
|
|
98
122
|
}
|
|
123
|
+
recursivelyAddNodeToSymbolTable(nodeData) {
|
|
124
|
+
if (!nodeData) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
let nodeType;
|
|
128
|
+
const nodeName = util_1.util.getSgNodeTypeName(nodeData.name);
|
|
129
|
+
if (!this.globalScope.symbolTable.hasSymbol(nodeName, SymbolTable_1.SymbolTypeFlag.typetime)) {
|
|
130
|
+
let parentNode;
|
|
131
|
+
if (nodeData.extends) {
|
|
132
|
+
const parentNodeData = roku_types_1.nodes[nodeData.extends.name.toLowerCase()];
|
|
133
|
+
try {
|
|
134
|
+
parentNode = this.recursivelyAddNodeToSymbolTable(parentNodeData);
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
console.log(error, nodeData);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
nodeType = new ComponentType_1.ComponentType(nodeData.name, parentNode);
|
|
141
|
+
nodeType.addBuiltInInterfaces();
|
|
142
|
+
this.globalScope.symbolTable.addSymbol(nodeName, { description: nodeData.description }, nodeType, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
nodeType = this.globalScope.symbolTable.getSymbolType(nodeName, { flags: SymbolTable_1.SymbolTypeFlag.typetime });
|
|
146
|
+
}
|
|
147
|
+
return nodeType;
|
|
148
|
+
}
|
|
99
149
|
/**
|
|
100
150
|
* Do all setup required for the global symbol table.
|
|
101
151
|
*/
|
|
102
152
|
populateGlobalSymbolTable() {
|
|
103
153
|
//Setup primitive types in global symbolTable
|
|
104
|
-
//TODO: Need to handle Array types
|
|
105
154
|
this.globalScope.symbolTable.addSymbol('boolean', undefined, BooleanType_1.BooleanType.instance, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
106
155
|
this.globalScope.symbolTable.addSymbol('double', undefined, DoubleType_1.DoubleType.instance, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
107
156
|
this.globalScope.symbolTable.addSymbol('dynamic', undefined, DynamicType_1.DynamicType.instance, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
@@ -112,9 +161,27 @@ class Program {
|
|
|
112
161
|
this.globalScope.symbolTable.addSymbol('object', undefined, new ObjectType_1.ObjectType(), SymbolTable_1.SymbolTypeFlag.typetime);
|
|
113
162
|
this.globalScope.symbolTable.addSymbol('string', undefined, StringType_1.StringType.instance, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
114
163
|
this.globalScope.symbolTable.addSymbol('void', undefined, VoidType_1.VoidType.instance, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
this.globalScope.symbolTable.addSymbol(
|
|
164
|
+
BuiltInInterfaceAdder_1.BuiltInInterfaceAdder.getLookupTable = () => this.globalScope.symbolTable;
|
|
165
|
+
for (const callable of globalCallables_1.globalCallables) {
|
|
166
|
+
this.globalScope.symbolTable.addSymbol(callable.name, { description: callable.shortDescription }, callable.type, SymbolTable_1.SymbolTypeFlag.runtime);
|
|
167
|
+
}
|
|
168
|
+
for (const componentData of Object.values(roku_types_1.components)) {
|
|
169
|
+
const nodeType = new types_1.InterfaceType(componentData.name);
|
|
170
|
+
nodeType.addBuiltInInterfaces();
|
|
171
|
+
this.globalScope.symbolTable.addSymbol(componentData.name, { description: componentData.description }, nodeType, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
172
|
+
}
|
|
173
|
+
for (const ifaceData of Object.values(roku_types_1.interfaces)) {
|
|
174
|
+
const nodeType = new types_1.InterfaceType(ifaceData.name);
|
|
175
|
+
nodeType.addBuiltInInterfaces();
|
|
176
|
+
this.globalScope.symbolTable.addSymbol(ifaceData.name, { description: ifaceData.description }, nodeType, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
177
|
+
}
|
|
178
|
+
for (const eventData of Object.values(roku_types_1.events)) {
|
|
179
|
+
const nodeType = new types_1.InterfaceType(eventData.name);
|
|
180
|
+
nodeType.addBuiltInInterfaces();
|
|
181
|
+
this.globalScope.symbolTable.addSymbol(eventData.name, { description: eventData.description }, nodeType, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
182
|
+
}
|
|
183
|
+
for (const nodeData of Object.values(roku_types_1.nodes)) {
|
|
184
|
+
this.recursivelyAddNodeToSymbolTable(nodeData);
|
|
118
185
|
}
|
|
119
186
|
}
|
|
120
187
|
/**
|
|
@@ -131,7 +198,7 @@ class Program {
|
|
|
131
198
|
//default to the embedded version
|
|
132
199
|
}
|
|
133
200
|
else {
|
|
134
|
-
return
|
|
201
|
+
return `${this.options.bslibDestinationDir}${path.sep}bslib.brs`;
|
|
135
202
|
}
|
|
136
203
|
}
|
|
137
204
|
get bslibPrefix() {
|
|
@@ -152,7 +219,7 @@ class Program {
|
|
|
152
219
|
var _a;
|
|
153
220
|
if (componentName) {
|
|
154
221
|
//return the first compoment in the list with this name
|
|
155
|
-
//(components are ordered in this list by
|
|
222
|
+
//(components are ordered in this list by destPath to ensure consistency)
|
|
156
223
|
return (_a = this.components[componentName.toLowerCase()]) === null || _a === void 0 ? void 0 : _a[0];
|
|
157
224
|
}
|
|
158
225
|
else {
|
|
@@ -163,8 +230,7 @@ class Program {
|
|
|
163
230
|
* Register (or replace) the reference to a component in the component map
|
|
164
231
|
*/
|
|
165
232
|
registerComponent(xmlFile, scope) {
|
|
166
|
-
|
|
167
|
-
const key = ((_b = (_a = xmlFile.componentName) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : xmlFile.pkgPath).toLowerCase();
|
|
233
|
+
const key = this.getComponentKey(xmlFile);
|
|
168
234
|
if (!this.components[key]) {
|
|
169
235
|
this.components[key] = [];
|
|
170
236
|
}
|
|
@@ -173,8 +239,8 @@ class Program {
|
|
|
173
239
|
scope: scope
|
|
174
240
|
});
|
|
175
241
|
this.components[key].sort((a, b) => {
|
|
176
|
-
const pathA = a.file.
|
|
177
|
-
const pathB = b.file.
|
|
242
|
+
const pathA = a.file.destPath.toLowerCase();
|
|
243
|
+
const pathB = b.file.destPath.toLowerCase();
|
|
178
244
|
if (pathA < pathB) {
|
|
179
245
|
return -1;
|
|
180
246
|
}
|
|
@@ -184,13 +250,13 @@ class Program {
|
|
|
184
250
|
return 0;
|
|
185
251
|
});
|
|
186
252
|
this.syncComponentDependencyGraph(this.components[key]);
|
|
253
|
+
this.addDeferredComponentTypeSymbolCreation(xmlFile);
|
|
187
254
|
}
|
|
188
255
|
/**
|
|
189
256
|
* Remove the specified component from the components map
|
|
190
257
|
*/
|
|
191
258
|
unregisterComponent(xmlFile) {
|
|
192
|
-
|
|
193
|
-
const key = ((_b = (_a = xmlFile.componentName) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : xmlFile.pkgPath).toLowerCase();
|
|
259
|
+
const key = this.getComponentKey(xmlFile);
|
|
194
260
|
const arr = this.components[key] || [];
|
|
195
261
|
for (let i = 0; i < arr.length; i++) {
|
|
196
262
|
if (arr[i].file === xmlFile) {
|
|
@@ -199,6 +265,44 @@ class Program {
|
|
|
199
265
|
}
|
|
200
266
|
}
|
|
201
267
|
this.syncComponentDependencyGraph(arr);
|
|
268
|
+
this.addDeferredComponentTypeSymbolCreation(xmlFile);
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Adds a component described in an XML to the set of components that needs to be updated this validation cycle.
|
|
272
|
+
* @param xmlFile XML file with <component> tag
|
|
273
|
+
*/
|
|
274
|
+
addDeferredComponentTypeSymbolCreation(xmlFile) {
|
|
275
|
+
var _a;
|
|
276
|
+
this.componentSymbolsToUpdate.add({ componentKey: this.getComponentKey(xmlFile), componentName: (_a = xmlFile.componentName) === null || _a === void 0 ? void 0 : _a.text });
|
|
277
|
+
}
|
|
278
|
+
getComponentKey(xmlFile) {
|
|
279
|
+
var _a, _b;
|
|
280
|
+
return ((_b = (_a = xmlFile.componentName) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : xmlFile.pkgPath).toLowerCase();
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Updates the global symbol table with the first component in this.components to have the same name as the component in the file
|
|
284
|
+
* @param componentKey key getting a component from `this.components`
|
|
285
|
+
* @param componentName the unprefixed name of the component that will be added (e.g. 'MyLabel' NOT 'roSgNodeMyLabel')
|
|
286
|
+
*/
|
|
287
|
+
updateComponentSymbolInGlobalScope(componentKey, componentName) {
|
|
288
|
+
const symbolName = componentName ? util_1.util.getSgNodeTypeName(componentName) : undefined;
|
|
289
|
+
if (!symbolName) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
const components = this.components[componentKey] || [];
|
|
293
|
+
// Remove any existing symbols that match
|
|
294
|
+
this.globalScope.symbolTable.removeSymbol(symbolName);
|
|
295
|
+
// There is a component that can be added - use it.
|
|
296
|
+
if (components.length > 0) {
|
|
297
|
+
const componentScope = components[0].scope;
|
|
298
|
+
// TODO: May need to link symbol tables to get correct types for callfuncs
|
|
299
|
+
// componentScope.linkSymbolTable();
|
|
300
|
+
const componentType = componentScope.getComponentType();
|
|
301
|
+
if (componentType) {
|
|
302
|
+
this.globalScope.symbolTable.addSymbol(symbolName, {}, componentType, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
303
|
+
}
|
|
304
|
+
// TODO: Remember to unlink! componentScope.unlinkSymbolTable();
|
|
305
|
+
}
|
|
202
306
|
}
|
|
203
307
|
/**
|
|
204
308
|
* re-attach the dependency graph with a new key for any component who changed
|
|
@@ -212,6 +316,7 @@ class Program {
|
|
|
212
316
|
//attach (or re-attach) the dependencyGraph for every component whose position changed
|
|
213
317
|
if (file.dependencyGraphIndex !== i) {
|
|
214
318
|
file.dependencyGraphIndex = i;
|
|
319
|
+
this.dependencyGraph.addOrReplace(file.dependencyGraphKey, file.dependencies);
|
|
215
320
|
file.attachDependencyGraph(this.dependencyGraph);
|
|
216
321
|
scope.attachDependencyGraph(this.dependencyGraph);
|
|
217
322
|
}
|
|
@@ -248,7 +353,7 @@ class Program {
|
|
|
248
353
|
//get the diagnostics from all unreferenced files
|
|
249
354
|
let unreferencedFiles = this.getUnreferencedFiles();
|
|
250
355
|
for (let file of unreferencedFiles) {
|
|
251
|
-
diagnostics.push(...file.
|
|
356
|
+
diagnostics.push(...file.diagnostics);
|
|
252
357
|
}
|
|
253
358
|
const filteredDiagnostics = this.logger.time(Logger_1.LogLevel.debug, ['filter diagnostics'], () => {
|
|
254
359
|
//filter out diagnostics based on our diagnostic filters
|
|
@@ -273,11 +378,9 @@ class Program {
|
|
|
273
378
|
hasFile(filePath, normalizePath = true) {
|
|
274
379
|
return !!this.getFile(filePath, normalizePath);
|
|
275
380
|
}
|
|
276
|
-
getPkgPath(...args) {
|
|
277
|
-
throw new Error('Not implemented');
|
|
278
|
-
}
|
|
279
381
|
/**
|
|
280
382
|
* roku filesystem is case INsensitive, so find the scope by key case insensitive
|
|
383
|
+
* @param scopeName xml scope names are their `destPath`. Source scope is stored with the key `"source"`
|
|
281
384
|
*/
|
|
282
385
|
getScopeByName(scopeName) {
|
|
283
386
|
if (!scopeName) {
|
|
@@ -306,8 +409,14 @@ class Program {
|
|
|
306
409
|
* Update internal maps with this file reference
|
|
307
410
|
*/
|
|
308
411
|
assignFile(file) {
|
|
412
|
+
const fileAddEvent = {
|
|
413
|
+
file: file,
|
|
414
|
+
program: this
|
|
415
|
+
};
|
|
416
|
+
this.plugins.emit('beforeFileAdd', fileAddEvent);
|
|
309
417
|
this.files[file.srcPath.toLowerCase()] = file;
|
|
310
|
-
this.
|
|
418
|
+
this.destMap.set(file.destPath.toLowerCase(), file);
|
|
419
|
+
this.plugins.emit('afterFileAdd', fileAddEvent);
|
|
311
420
|
return file;
|
|
312
421
|
}
|
|
313
422
|
/**
|
|
@@ -315,104 +424,102 @@ class Program {
|
|
|
315
424
|
*/
|
|
316
425
|
unassignFile(file) {
|
|
317
426
|
delete this.files[file.srcPath.toLowerCase()];
|
|
318
|
-
|
|
427
|
+
this.destMap.delete(file.destPath.toLowerCase());
|
|
319
428
|
return file;
|
|
320
429
|
}
|
|
321
|
-
setFile(fileParam,
|
|
430
|
+
setFile(fileParam, fileData) {
|
|
322
431
|
//normalize the file paths
|
|
323
|
-
const { srcPath,
|
|
432
|
+
const { srcPath, destPath } = this.getPaths(fileParam, this.options.rootDir);
|
|
324
433
|
let file = this.logger.time(Logger_1.LogLevel.debug, ['Program.setFile()', chalk_1.default.green(srcPath)], () => {
|
|
434
|
+
var _a, _b, _c;
|
|
325
435
|
//if the file is already loaded, remove it
|
|
326
436
|
if (this.hasFile(srcPath)) {
|
|
327
437
|
this.removeFile(srcPath);
|
|
328
438
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
source: fileContents
|
|
343
|
-
};
|
|
344
|
-
this.plugins.emit('beforeFileParse', beforeFileParseEvent);
|
|
345
|
-
this.logger.time(Logger_1.LogLevel.debug, ['parse', chalk_1.default.green(srcPath)], () => {
|
|
346
|
-
brsFile.parse(beforeFileParseEvent.source);
|
|
347
|
-
});
|
|
348
|
-
//notify plugins that this file has finished parsing
|
|
349
|
-
this.plugins.emit('afterFileParse', {
|
|
350
|
-
program: this,
|
|
351
|
-
file: brsFile
|
|
352
|
-
});
|
|
353
|
-
file = brsFile;
|
|
354
|
-
brsFile.attachDependencyGraph(this.dependencyGraph);
|
|
439
|
+
const data = new LazyFileData_1.LazyFileData(fileData);
|
|
440
|
+
const event = new ProvideFileEventInternal(this, srcPath, destPath, data, this.fileFactory);
|
|
441
|
+
this.plugins.emit('beforeProvideFile', event);
|
|
442
|
+
this.plugins.emit('provideFile', event);
|
|
443
|
+
this.plugins.emit('afterProvideFile', event);
|
|
444
|
+
//if no files were provided, create a AssetFile to represent it.
|
|
445
|
+
if (event.files.length === 0) {
|
|
446
|
+
event.files.push(this.fileFactory.AssetFile({
|
|
447
|
+
srcPath: event.srcPath,
|
|
448
|
+
destPath: event.destPath,
|
|
449
|
+
pkgPath: event.destPath,
|
|
450
|
+
data: data
|
|
451
|
+
}));
|
|
355
452
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
program: this,
|
|
365
|
-
srcPath: srcPath,
|
|
366
|
-
source: fileContents
|
|
367
|
-
};
|
|
368
|
-
this.plugins.emit('beforeFileParse', event);
|
|
369
|
-
this.logger.time(Logger_1.LogLevel.debug, ['parse', chalk_1.default.green(srcPath)], () => {
|
|
370
|
-
xmlFile.parse(event.source);
|
|
371
|
-
});
|
|
372
|
-
//notify plugins that this file has finished parsing
|
|
373
|
-
this.plugins.emit('afterFileParse', {
|
|
374
|
-
program: this,
|
|
375
|
-
file: xmlFile
|
|
376
|
-
});
|
|
377
|
-
file = xmlFile;
|
|
378
|
-
//create a new scope for this xml file
|
|
379
|
-
let scope = new XmlScope_1.XmlScope(xmlFile, this);
|
|
380
|
-
this.addScope(scope);
|
|
381
|
-
//register this compoent now that we have parsed it and know its component name
|
|
382
|
-
this.registerComponent(xmlFile, scope);
|
|
383
|
-
//notify plugins that the scope is created and the component is registered
|
|
384
|
-
this.plugins.emit('afterScopeCreate', {
|
|
385
|
-
program: this,
|
|
386
|
-
scope: scope
|
|
387
|
-
});
|
|
453
|
+
//find the file instance for the srcPath that triggered this action.
|
|
454
|
+
const primaryFile = event.files.find(x => x.srcPath === srcPath);
|
|
455
|
+
if (!primaryFile) {
|
|
456
|
+
throw new Error(`No file provided for srcPath '${srcPath}'. Instead, received ${JSON.stringify(event.files.map(x => ({
|
|
457
|
+
type: x.type,
|
|
458
|
+
srcPath: x.srcPath,
|
|
459
|
+
destPath: x.destPath
|
|
460
|
+
})))}`);
|
|
388
461
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
462
|
+
//link the virtual files to the primary file
|
|
463
|
+
this.fileClusters.set((_a = primaryFile.srcPath) === null || _a === void 0 ? void 0 : _a.toLowerCase(), event.files);
|
|
464
|
+
for (const file of event.files) {
|
|
465
|
+
file.srcPath = (0, util_1.standardizePath)(file.srcPath);
|
|
466
|
+
if (file.destPath) {
|
|
467
|
+
file.destPath = (0, util_1.standardizePath) `${util_1.util.replaceCaseInsensitive(file.destPath, this.options.rootDir, '')}`;
|
|
468
|
+
}
|
|
469
|
+
if (file.pkgPath) {
|
|
470
|
+
file.pkgPath = (0, util_1.standardizePath) `${util_1.util.replaceCaseInsensitive(file.pkgPath, this.options.rootDir, '')}`;
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
file.pkgPath = file.destPath;
|
|
474
|
+
}
|
|
475
|
+
file.excludeFromOutput = file.excludeFromOutput === true;
|
|
476
|
+
//set the dependencyGraph key for every file to its destPath
|
|
477
|
+
file.dependencyGraphKey = file.destPath.toLowerCase();
|
|
478
|
+
this.assignFile(file);
|
|
479
|
+
//register a callback anytime this file's dependencies change
|
|
480
|
+
if (typeof file.onDependenciesChanged === 'function') {
|
|
481
|
+
(_b = file.disposables) !== null && _b !== void 0 ? _b : (file.disposables = []);
|
|
482
|
+
file.disposables.push(this.dependencyGraph.onchange(file.dependencyGraphKey, file.onDependenciesChanged.bind(file)));
|
|
483
|
+
}
|
|
484
|
+
//register this file (and its dependencies) with the dependency graph
|
|
485
|
+
this.dependencyGraph.addOrReplace(file.dependencyGraphKey, (_c = file.dependencies) !== null && _c !== void 0 ? _c : []);
|
|
486
|
+
//if this is a `source` file, add it to the source scope's dependency list
|
|
487
|
+
if (this.isSourceBrsFile(file)) {
|
|
488
|
+
this.createSourceScope();
|
|
489
|
+
this.dependencyGraph.addDependency('scope:source', file.dependencyGraphKey);
|
|
490
|
+
}
|
|
491
|
+
//if this is an xml file in the components folder, register it as a component
|
|
492
|
+
if (this.isComponentsXmlFile(file)) {
|
|
493
|
+
//create a new scope for this xml file
|
|
494
|
+
let scope = new XmlScope_1.XmlScope(file, this);
|
|
495
|
+
this.addScope(scope);
|
|
496
|
+
//register this compoent now that we have parsed it and know its component name
|
|
497
|
+
this.registerComponent(file, scope);
|
|
498
|
+
//notify plugins that the scope is created and the component is registered
|
|
499
|
+
this.plugins.emit('afterScopeCreate', {
|
|
500
|
+
program: this,
|
|
501
|
+
scope: scope
|
|
502
|
+
});
|
|
503
|
+
}
|
|
397
504
|
}
|
|
398
|
-
return
|
|
505
|
+
return primaryFile;
|
|
399
506
|
});
|
|
400
507
|
return file;
|
|
401
508
|
}
|
|
402
509
|
/**
|
|
403
|
-
* Given a srcPath, a
|
|
510
|
+
* Given a srcPath, a destPath, or both, resolve whichever is missing, relative to rootDir.
|
|
404
511
|
* @param fileParam an object representing file paths
|
|
405
512
|
* @param rootDir must be a pre-normalized path
|
|
406
513
|
*/
|
|
407
514
|
getPaths(fileParam, rootDir) {
|
|
408
515
|
let srcPath;
|
|
409
|
-
let
|
|
516
|
+
let destPath;
|
|
410
517
|
assert.ok(fileParam, 'fileParam is required');
|
|
411
|
-
//lift the
|
|
518
|
+
//lift the path vars from the incoming param
|
|
412
519
|
if (typeof fileParam === 'string') {
|
|
413
520
|
fileParam = this.removePkgPrefix(fileParam);
|
|
414
521
|
srcPath = (0, util_1.standardizePath) `${path.resolve(rootDir, fileParam)}`;
|
|
415
|
-
|
|
522
|
+
destPath = (0, util_1.standardizePath) `${util_1.util.replaceCaseInsensitive(srcPath, rootDir, '')}`;
|
|
416
523
|
}
|
|
417
524
|
else {
|
|
418
525
|
let param = fileParam;
|
|
@@ -423,30 +530,30 @@ class Program {
|
|
|
423
530
|
srcPath = (0, util_1.standardizePath) `${param.srcPath}`;
|
|
424
531
|
}
|
|
425
532
|
if (param.dest) {
|
|
426
|
-
|
|
533
|
+
destPath = (0, util_1.standardizePath) `${this.removePkgPrefix(param.dest)}`;
|
|
427
534
|
}
|
|
428
535
|
if (param.pkgPath) {
|
|
429
|
-
|
|
536
|
+
destPath = (0, util_1.standardizePath) `${this.removePkgPrefix(param.pkgPath)}`;
|
|
430
537
|
}
|
|
431
538
|
}
|
|
432
|
-
//if there's no srcPath, use the
|
|
539
|
+
//if there's no srcPath, use the destPath to build an absolute srcPath
|
|
433
540
|
if (!srcPath) {
|
|
434
|
-
srcPath = (0, util_1.standardizePath) `${rootDir}/${
|
|
541
|
+
srcPath = (0, util_1.standardizePath) `${rootDir}/${destPath}`;
|
|
435
542
|
}
|
|
436
543
|
//coerce srcPath to an absolute path
|
|
437
544
|
if (!path.isAbsolute(srcPath)) {
|
|
438
545
|
srcPath = util_1.util.standardizePath(srcPath);
|
|
439
546
|
}
|
|
440
|
-
//if
|
|
441
|
-
if (!
|
|
442
|
-
|
|
547
|
+
//if destPath isn't set, compute it from the other paths
|
|
548
|
+
if (!destPath) {
|
|
549
|
+
destPath = (0, util_1.standardizePath) `${util_1.util.replaceCaseInsensitive(srcPath, rootDir, '')}`;
|
|
443
550
|
}
|
|
444
551
|
assert.ok(srcPath, 'fileEntry.src is required');
|
|
445
|
-
assert.ok(
|
|
552
|
+
assert.ok(destPath, 'fileEntry.dest is required');
|
|
446
553
|
return {
|
|
447
554
|
srcPath: srcPath,
|
|
448
|
-
//remove leading slash
|
|
449
|
-
|
|
555
|
+
//remove leading slash
|
|
556
|
+
destPath: destPath.replace(/^[\/\\]+/, '')
|
|
450
557
|
};
|
|
451
558
|
}
|
|
452
559
|
/**
|
|
@@ -455,6 +562,18 @@ class Program {
|
|
|
455
562
|
removePkgPrefix(path) {
|
|
456
563
|
return path.replace(/^pkg:\//i, '');
|
|
457
564
|
}
|
|
565
|
+
/**
|
|
566
|
+
* Is this file a .brs file found somewhere within the `pkg:/source/` folder?
|
|
567
|
+
*/
|
|
568
|
+
isSourceBrsFile(file) {
|
|
569
|
+
return !!/^(pkg:\/)?source[\/\\]/.exec(file.destPath);
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Is this file a .brs file found somewhere within the `pkg:/source/` folder?
|
|
573
|
+
*/
|
|
574
|
+
isComponentsXmlFile(file) {
|
|
575
|
+
return (0, reflection_1.isXmlFile)(file) && !!/^(pkg:\/)?components[\/\\]/.exec(file.destPath);
|
|
576
|
+
}
|
|
458
577
|
/**
|
|
459
578
|
* Ensure source scope is created.
|
|
460
579
|
* Note: automatically called internally, and no-op if it exists already.
|
|
@@ -482,46 +601,55 @@ class Program {
|
|
|
482
601
|
}
|
|
483
602
|
/**
|
|
484
603
|
* Remove a file from the program
|
|
485
|
-
* @param filePath can be a srcPath, a
|
|
604
|
+
* @param filePath can be a srcPath, a destPath, or a destPath with leading `pkg:/`
|
|
486
605
|
* @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
|
|
487
606
|
*/
|
|
488
607
|
removeFile(filePath, normalizePath = true) {
|
|
608
|
+
var _a, _b, _c, _d;
|
|
489
609
|
this.logger.debug('Program.removeFile()', filePath);
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
610
|
+
const paths = this.getPaths(filePath, this.options.rootDir);
|
|
611
|
+
//there can be one or more File entries for a single srcPath, so get all of them and remove them all
|
|
612
|
+
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)];
|
|
613
|
+
for (const file of files) {
|
|
614
|
+
//if a file has already been removed, nothing more needs to be done here
|
|
615
|
+
if (!file || !this.hasFile(file.srcPath)) {
|
|
616
|
+
continue;
|
|
617
|
+
}
|
|
618
|
+
const event = { file: file, program: this };
|
|
619
|
+
this.plugins.emit('beforeFileRemove', event);
|
|
497
620
|
//if there is a scope named the same as this file's path, remove it (i.e. xml scopes)
|
|
498
|
-
let scope = this.scopes[file.
|
|
621
|
+
let scope = this.scopes[file.destPath];
|
|
499
622
|
if (scope) {
|
|
500
623
|
const scopeDisposeEvent = {
|
|
501
624
|
program: this,
|
|
502
625
|
scope: scope
|
|
503
626
|
};
|
|
504
627
|
this.plugins.emit('beforeScopeDispose', scopeDisposeEvent);
|
|
628
|
+
this.plugins.emit('onScopeDispose', scopeDisposeEvent);
|
|
505
629
|
scope.dispose();
|
|
506
630
|
//notify dependencies of this scope that it has been removed
|
|
507
631
|
this.dependencyGraph.remove(scope.dependencyGraphKey);
|
|
508
|
-
delete this.scopes[file.
|
|
632
|
+
delete this.scopes[file.destPath];
|
|
509
633
|
this.plugins.emit('afterScopeDispose', scopeDisposeEvent);
|
|
510
634
|
}
|
|
511
635
|
//remove the file from the program
|
|
512
636
|
this.unassignFile(file);
|
|
513
637
|
this.dependencyGraph.remove(file.dependencyGraphKey);
|
|
514
638
|
//if this is a pkg:/source file, notify the `source` scope that it has changed
|
|
515
|
-
if (
|
|
639
|
+
if (this.isSourceBrsFile(file)) {
|
|
516
640
|
this.dependencyGraph.removeDependency('scope:source', file.dependencyGraphKey);
|
|
517
641
|
}
|
|
518
642
|
//if this is a component, remove it from our components map
|
|
519
643
|
if ((0, reflection_1.isXmlFile)(file)) {
|
|
520
644
|
this.unregisterComponent(file);
|
|
521
645
|
}
|
|
646
|
+
//dispose any disposable things on the file
|
|
647
|
+
for (const disposable of (_c = file === null || file === void 0 ? void 0 : file.disposables) !== null && _c !== void 0 ? _c : []) {
|
|
648
|
+
disposable();
|
|
649
|
+
}
|
|
522
650
|
//dispose file
|
|
523
|
-
file === null || file === void 0 ? void 0 : file.dispose();
|
|
524
|
-
this.plugins.emit('
|
|
651
|
+
(_d = file === null || file === void 0 ? void 0 : file.dispose) === null || _d === void 0 ? void 0 : _d.call(file);
|
|
652
|
+
this.plugins.emit('afterFileRemove', event);
|
|
525
653
|
}
|
|
526
654
|
}
|
|
527
655
|
/**
|
|
@@ -534,6 +662,7 @@ class Program {
|
|
|
534
662
|
program: this
|
|
535
663
|
};
|
|
536
664
|
this.plugins.emit('beforeProgramValidate', programValidateEvent);
|
|
665
|
+
this.plugins.emit('onProgramValidate', programValidateEvent);
|
|
537
666
|
//validate every file
|
|
538
667
|
for (const file of Object.values(this.files)) {
|
|
539
668
|
//for every unvalidated file, validate it
|
|
@@ -549,6 +678,13 @@ class Program {
|
|
|
549
678
|
this.plugins.emit('afterFileValidate', validateFileEvent);
|
|
550
679
|
}
|
|
551
680
|
}
|
|
681
|
+
// Build component types for any component that changes
|
|
682
|
+
this.logger.time(Logger_1.LogLevel.info, ['Build component types'], () => {
|
|
683
|
+
for (let { componentKey, componentName } of this.componentSymbolsToUpdate) {
|
|
684
|
+
this.updateComponentSymbolInGlobalScope(componentKey, componentName);
|
|
685
|
+
}
|
|
686
|
+
this.componentSymbolsToUpdate.clear();
|
|
687
|
+
});
|
|
552
688
|
this.logger.time(Logger_1.LogLevel.info, ['Validate all scopes'], () => {
|
|
553
689
|
for (let scopeName in this.scopes) {
|
|
554
690
|
let scope = this.scopes[scopeName];
|
|
@@ -611,12 +747,13 @@ class Program {
|
|
|
611
747
|
getFile(filePath, normalizePath = true) {
|
|
612
748
|
if (typeof filePath !== 'string') {
|
|
613
749
|
return undefined;
|
|
750
|
+
//is the path absolute (or the `virtual:` prefix)
|
|
614
751
|
}
|
|
615
|
-
else if (
|
|
752
|
+
else if (/^(?:(?:virtual:[\/\\])|(?:\w:)|(?:[\/\\]))/gmi.exec(filePath)) {
|
|
616
753
|
return this.files[(normalizePath ? util_1.util.standardizePath(filePath) : filePath).toLowerCase()];
|
|
617
754
|
}
|
|
618
755
|
else {
|
|
619
|
-
return this.
|
|
756
|
+
return this.destMap.get((normalizePath ? util_1.util.standardizePath(filePath) : filePath).toLowerCase());
|
|
620
757
|
}
|
|
621
758
|
}
|
|
622
759
|
/**
|
|
@@ -658,7 +795,8 @@ class Program {
|
|
|
658
795
|
//look through all files in scope for matches
|
|
659
796
|
for (const scope of this.getScopesForFile(originFile)) {
|
|
660
797
|
for (const file of scope.getAllFiles()) {
|
|
661
|
-
|
|
798
|
+
//skip non-brs files, or files we've already processed
|
|
799
|
+
if (!(0, reflection_1.isBrsFile)(file) || filesSearched.has(file)) {
|
|
662
800
|
continue;
|
|
663
801
|
}
|
|
664
802
|
filesSearched.add(file);
|
|
@@ -691,7 +829,8 @@ class Program {
|
|
|
691
829
|
}
|
|
692
830
|
//look through all files in scope for matches
|
|
693
831
|
for (const file of scope.getOwnFiles()) {
|
|
694
|
-
|
|
832
|
+
//skip non-brs files, or files we've already processed
|
|
833
|
+
if (!(0, reflection_1.isBrsFile)(file) || filesSearched.has(file)) {
|
|
695
834
|
continue;
|
|
696
835
|
}
|
|
697
836
|
filesSearched.add(file);
|
|
@@ -840,10 +979,12 @@ class Program {
|
|
|
840
979
|
getReferences(srcPath, position) {
|
|
841
980
|
//find the file
|
|
842
981
|
let file = this.getFile(srcPath);
|
|
843
|
-
if (
|
|
982
|
+
if ((0, reflection_1.isBrsFile)(file) || (0, reflection_1.isXmlFile)(file)) {
|
|
983
|
+
return file.getReferences(position);
|
|
984
|
+
}
|
|
985
|
+
else {
|
|
844
986
|
return null;
|
|
845
987
|
}
|
|
846
|
-
return file.getReferences(position);
|
|
847
988
|
}
|
|
848
989
|
/**
|
|
849
990
|
* Transpile a single file and get the result as a string.
|
|
@@ -854,168 +995,211 @@ class Program {
|
|
|
854
995
|
* @param filePath can be a srcPath or a destPath
|
|
855
996
|
*/
|
|
856
997
|
async getTranspiledFileContents(filePath) {
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
998
|
+
const file = this.getFile(filePath);
|
|
999
|
+
return this.getTranspiledFileContentsPipeline.run(async () => {
|
|
1000
|
+
const result = {
|
|
1001
|
+
destPath: file.destPath,
|
|
1002
|
+
pkgPath: file.pkgPath,
|
|
1003
|
+
srcPath: file.srcPath
|
|
1004
|
+
};
|
|
1005
|
+
const expectedPkgPath = file.pkgPath.toLowerCase();
|
|
1006
|
+
const expectedMapPath = `${expectedPkgPath}.map`;
|
|
1007
|
+
const expectedTypedefPkgPath = expectedPkgPath.replace(/\.brs$/i, '.d.bs');
|
|
1008
|
+
//add a temporary plugin to tap into the file writing process
|
|
1009
|
+
const plugin = this.plugins.addFirst({
|
|
1010
|
+
name: 'getTranspiledFileContents',
|
|
1011
|
+
beforeWriteFile: (event) => {
|
|
1012
|
+
const pkgPath = event.file.pkgPath.toLowerCase();
|
|
1013
|
+
switch (pkgPath) {
|
|
1014
|
+
//this is the actual transpiled file
|
|
1015
|
+
case expectedPkgPath:
|
|
1016
|
+
result.code = event.file.data.toString();
|
|
1017
|
+
break;
|
|
1018
|
+
//this is the sourcemap
|
|
1019
|
+
case expectedMapPath:
|
|
1020
|
+
result.map = event.file.data.toString();
|
|
1021
|
+
break;
|
|
1022
|
+
//this is the typedef
|
|
1023
|
+
case expectedTypedefPkgPath:
|
|
1024
|
+
result.typedef = event.file.data.toString();
|
|
1025
|
+
break;
|
|
1026
|
+
default:
|
|
1027
|
+
//no idea what this file is. just ignore it
|
|
1028
|
+
}
|
|
1029
|
+
//mark every file as processed so it they don't get written to the output directory
|
|
1030
|
+
event.processedFiles.add(event.file);
|
|
1031
|
+
}
|
|
1032
|
+
});
|
|
1033
|
+
try {
|
|
1034
|
+
//now that the plugin has been registered, run the build with just this file
|
|
1035
|
+
await this.build({
|
|
1036
|
+
files: [file]
|
|
1037
|
+
});
|
|
1038
|
+
}
|
|
1039
|
+
finally {
|
|
1040
|
+
this.plugins.remove(plugin);
|
|
863
1041
|
}
|
|
1042
|
+
return result;
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
/**
|
|
1046
|
+
* Get the absolute output path for a file
|
|
1047
|
+
*/
|
|
1048
|
+
getOutputPath(file, stagingDir = this.getStagingDir()) {
|
|
1049
|
+
return (0, util_1.standardizePath) `${stagingDir}/${file.pkgPath}`;
|
|
1050
|
+
}
|
|
1051
|
+
getStagingDir(stagingDir) {
|
|
1052
|
+
var _a, _b;
|
|
1053
|
+
let result = (_a = stagingDir !== null && stagingDir !== void 0 ? stagingDir : this.options.stagingDir) !== null && _a !== void 0 ? _a : this.options.stagingDir;
|
|
1054
|
+
if (!result) {
|
|
1055
|
+
result = roku_deploy_1.rokuDeploy.getOptions(this.options).stagingDir;
|
|
864
1056
|
}
|
|
865
|
-
|
|
866
|
-
const result = this._getTranspiledFileContents(this.getFile(filePath));
|
|
867
|
-
this.afterProgramTranspile(entries, astEditor);
|
|
1057
|
+
result = (0, util_1.standardizePath) `${path.resolve((_b = this.options.cwd) !== null && _b !== void 0 ? _b : process.cwd(), result !== null && result !== void 0 ? result : '/')}`;
|
|
868
1058
|
return result;
|
|
869
1059
|
}
|
|
870
1060
|
/**
|
|
871
|
-
*
|
|
872
|
-
*
|
|
1061
|
+
* Prepare the program for building
|
|
1062
|
+
* @param files the list of files that should be prepared
|
|
873
1063
|
*/
|
|
874
|
-
|
|
875
|
-
const
|
|
876
|
-
this.plugins.emit('beforeFileTranspile', {
|
|
877
|
-
program: this,
|
|
878
|
-
file: file,
|
|
879
|
-
outputPath: outputPath,
|
|
880
|
-
editor: editor
|
|
881
|
-
});
|
|
882
|
-
//if we have any edits, assume the file needs to be transpiled
|
|
883
|
-
if (editor.hasChanges) {
|
|
884
|
-
//use the `editor` because it'll track the previous value for us and revert later on
|
|
885
|
-
editor.setProperty(file, 'needsTranspiled', true);
|
|
886
|
-
}
|
|
887
|
-
//transpile the file
|
|
888
|
-
const result = file.transpile();
|
|
889
|
-
//generate the typedef if enabled
|
|
890
|
-
let typedef;
|
|
891
|
-
if ((0, reflection_1.isBrsFile)(file) && this.options.emitDefinitions) {
|
|
892
|
-
typedef = file.getTypedef();
|
|
893
|
-
}
|
|
894
|
-
const event = {
|
|
1064
|
+
async prepare(files) {
|
|
1065
|
+
const programEvent = {
|
|
895
1066
|
program: this,
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
editor: editor,
|
|
899
|
-
code: result.code,
|
|
900
|
-
map: result.map,
|
|
901
|
-
typedef: typedef
|
|
902
|
-
};
|
|
903
|
-
this.plugins.emit('afterFileTranspile', event);
|
|
904
|
-
//undo all `editor` edits that may have been applied to this file.
|
|
905
|
-
editor.undoAll();
|
|
906
|
-
return {
|
|
907
|
-
srcPath: file.srcPath,
|
|
908
|
-
pkgPath: file.pkgPath,
|
|
909
|
-
code: event.code,
|
|
910
|
-
map: event.map,
|
|
911
|
-
typedef: event.typedef
|
|
1067
|
+
editor: this.editor,
|
|
1068
|
+
files: files
|
|
912
1069
|
};
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
return collection;
|
|
919
|
-
}, {});
|
|
920
|
-
const getOutputPath = (file) => {
|
|
921
|
-
let filePathObj = mappedFileEntries[(0, util_1.standardizePath) `${file.srcPath}`];
|
|
922
|
-
if (!filePathObj) {
|
|
923
|
-
//this file has been added in-memory, from a plugin, for example
|
|
924
|
-
filePathObj = {
|
|
925
|
-
//add an interpolated src path (since it doesn't actually exist in memory)
|
|
926
|
-
src: `bsc:/${file.pkgPath}`,
|
|
927
|
-
dest: file.pkgPath
|
|
928
|
-
};
|
|
1070
|
+
//assign an editor to every file
|
|
1071
|
+
for (const file of files) {
|
|
1072
|
+
//if the file doesn't have an editor yet, assign one now
|
|
1073
|
+
if (!file.editor) {
|
|
1074
|
+
file.editor = new Editor_1.Editor();
|
|
929
1075
|
}
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
1076
|
+
}
|
|
1077
|
+
files.sort((a, b) => {
|
|
1078
|
+
if (a.pkgPath < b.pkgPath) {
|
|
1079
|
+
return -1;
|
|
1080
|
+
}
|
|
1081
|
+
else if (a.pkgPath > b.pkgPath) {
|
|
1082
|
+
return 1;
|
|
1083
|
+
}
|
|
1084
|
+
else {
|
|
1085
|
+
return 1;
|
|
1086
|
+
}
|
|
1087
|
+
});
|
|
1088
|
+
await this.plugins.emitAsync('beforePrepareProgram', programEvent);
|
|
1089
|
+
await this.plugins.emitAsync('prepareProgram', programEvent);
|
|
1090
|
+
const stagingDir = this.getStagingDir();
|
|
1091
|
+
const entries = [];
|
|
1092
|
+
for (const file of files) {
|
|
1093
|
+
//if the file doesn't have an editor yet, assign one now
|
|
1094
|
+
if (!file.editor) {
|
|
1095
|
+
file.editor = new Editor_1.Editor();
|
|
1096
|
+
}
|
|
1097
|
+
const event = {
|
|
1098
|
+
program: this,
|
|
938
1099
|
file: file,
|
|
939
|
-
|
|
1100
|
+
editor: file.editor,
|
|
1101
|
+
outputPath: this.getOutputPath(file, stagingDir)
|
|
940
1102
|
};
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
1103
|
+
await this.plugins.emitAsync('beforePrepareFile', event);
|
|
1104
|
+
await this.plugins.emitAsync('prepareFile', event);
|
|
1105
|
+
await this.plugins.emitAsync('afterPrepareFile', event);
|
|
1106
|
+
//TODO remove this in v1
|
|
1107
|
+
entries.push(event);
|
|
1108
|
+
}
|
|
1109
|
+
await this.plugins.emitAsync('afterPrepareProgram', programEvent);
|
|
1110
|
+
return files;
|
|
1111
|
+
}
|
|
1112
|
+
/**
|
|
1113
|
+
* Generate the contents of every file
|
|
1114
|
+
*/
|
|
1115
|
+
async serialize(files) {
|
|
1116
|
+
const allFiles = new Map();
|
|
1117
|
+
const serializeProgramEvent = await this.plugins.emitAsync('beforeSerializeProgram', {
|
|
1118
|
+
program: this,
|
|
1119
|
+
files: files,
|
|
1120
|
+
result: allFiles
|
|
944
1121
|
});
|
|
945
|
-
|
|
946
|
-
this.plugins.emit('beforeProgramTranspile', {
|
|
1122
|
+
await this.plugins.emitAsync('onSerializeProgram', {
|
|
947
1123
|
program: this,
|
|
948
|
-
|
|
949
|
-
|
|
1124
|
+
files: files,
|
|
1125
|
+
result: allFiles
|
|
950
1126
|
});
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
astEditor: astEditor
|
|
955
|
-
};
|
|
956
|
-
}
|
|
957
|
-
async transpile(fileEntries, stagingDir) {
|
|
958
|
-
const { entries, getOutputPath, astEditor } = this.beforeProgramTranspile(fileEntries, stagingDir);
|
|
959
|
-
const processedFiles = new Set();
|
|
960
|
-
const transpileFile = async (srcPath, outputPath) => {
|
|
961
|
-
//find the file in the program
|
|
962
|
-
const file = this.getFile(srcPath);
|
|
963
|
-
//mark this file as processed so we don't process it more than once
|
|
964
|
-
processedFiles.add(outputPath === null || outputPath === void 0 ? void 0 : outputPath.toLowerCase());
|
|
965
|
-
//skip transpiling typedef files
|
|
966
|
-
if ((0, reflection_1.isBrsFile)(file) && file.isTypedef) {
|
|
967
|
-
return;
|
|
968
|
-
}
|
|
969
|
-
const fileTranspileResult = this._getTranspiledFileContents(file, outputPath);
|
|
970
|
-
//make sure the full dir path exists
|
|
971
|
-
await fsExtra.ensureDir(path.dirname(outputPath));
|
|
972
|
-
if (await fsExtra.pathExists(outputPath)) {
|
|
973
|
-
throw new Error(`Error while transpiling "${file.srcPath}". A file already exists at "${outputPath}" and will not be overwritten.`);
|
|
974
|
-
}
|
|
975
|
-
const writeMapPromise = fileTranspileResult.map ? fsExtra.writeFile(`${outputPath}.map`, fileTranspileResult.map.toString()) : null;
|
|
976
|
-
await Promise.all([
|
|
977
|
-
fsExtra.writeFile(outputPath, fileTranspileResult.code),
|
|
978
|
-
writeMapPromise
|
|
979
|
-
]);
|
|
980
|
-
if (fileTranspileResult.typedef) {
|
|
981
|
-
const typedefPath = outputPath.replace(/\.brs$/i, '.d.bs');
|
|
982
|
-
await fsExtra.writeFile(typedefPath, fileTranspileResult.typedef);
|
|
983
|
-
}
|
|
984
|
-
};
|
|
985
|
-
let promises = entries.map(async (entry) => {
|
|
986
|
-
var _a;
|
|
987
|
-
return transpileFile((_a = entry === null || entry === void 0 ? void 0 : entry.file) === null || _a === void 0 ? void 0 : _a.srcPath, entry.outputPath);
|
|
1127
|
+
//sort the entries to make transpiling more deterministic
|
|
1128
|
+
files = serializeProgramEvent.files.sort((a, b) => {
|
|
1129
|
+
return a.srcPath < b.srcPath ? -1 : 1;
|
|
988
1130
|
});
|
|
989
|
-
//
|
|
990
|
-
|
|
991
|
-
|
|
1131
|
+
// serialize each file
|
|
1132
|
+
for (const file of files) {
|
|
1133
|
+
const event = {
|
|
1134
|
+
program: this,
|
|
1135
|
+
file: file,
|
|
1136
|
+
result: allFiles
|
|
1137
|
+
};
|
|
1138
|
+
await this.plugins.emitAsync('beforeSerializeFile', event);
|
|
1139
|
+
await this.plugins.emitAsync('serializeFile', event);
|
|
1140
|
+
await this.plugins.emitAsync('afterSerializeFile', event);
|
|
992
1141
|
}
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
//this is a new file
|
|
1000
|
-
const outputPath = getOutputPath(file);
|
|
1001
|
-
if (!processedFiles.has(outputPath === null || outputPath === void 0 ? void 0 : outputPath.toLowerCase())) {
|
|
1002
|
-
promises.push(transpileFile(file === null || file === void 0 ? void 0 : file.srcPath, outputPath));
|
|
1003
|
-
}
|
|
1004
|
-
}
|
|
1005
|
-
if (promises.length > 0) {
|
|
1006
|
-
this.logger.info(`Transpiling ${promises.length} new files`);
|
|
1007
|
-
await Promise.all(promises);
|
|
1008
|
-
}
|
|
1009
|
-
} while (promises.length > 0);
|
|
1010
|
-
this.afterProgramTranspile(entries, astEditor);
|
|
1142
|
+
this.plugins.emit('afterSerializeProgram', {
|
|
1143
|
+
program: this,
|
|
1144
|
+
files: files,
|
|
1145
|
+
result: allFiles
|
|
1146
|
+
});
|
|
1147
|
+
return allFiles;
|
|
1011
1148
|
}
|
|
1012
|
-
|
|
1013
|
-
|
|
1149
|
+
/**
|
|
1150
|
+
* Write the entire project to disk
|
|
1151
|
+
*/
|
|
1152
|
+
async write(stagingDir, files) {
|
|
1153
|
+
const programEvent = await this.plugins.emitAsync('beforeWriteProgram', {
|
|
1014
1154
|
program: this,
|
|
1015
|
-
|
|
1016
|
-
|
|
1155
|
+
files: files,
|
|
1156
|
+
stagingDir: stagingDir
|
|
1157
|
+
});
|
|
1158
|
+
//empty the staging directory
|
|
1159
|
+
await fsExtra.emptyDir(stagingDir);
|
|
1160
|
+
const serializedFiles = [...files]
|
|
1161
|
+
.map(([, serializedFiles]) => serializedFiles)
|
|
1162
|
+
.flat();
|
|
1163
|
+
//write all the files to disk (asynchronously)
|
|
1164
|
+
await Promise.all(serializedFiles.map(async (file) => {
|
|
1165
|
+
const event = await this.plugins.emitAsync('beforeWriteFile', {
|
|
1166
|
+
program: this,
|
|
1167
|
+
file: file,
|
|
1168
|
+
outputPath: this.getOutputPath(file, stagingDir),
|
|
1169
|
+
processedFiles: new Set()
|
|
1170
|
+
});
|
|
1171
|
+
await this.plugins.emitAsync('writeFile', event);
|
|
1172
|
+
await this.plugins.emitAsync('afterWriteFile', event);
|
|
1173
|
+
}));
|
|
1174
|
+
await this.plugins.emitAsync('afterWriteProgram', programEvent);
|
|
1175
|
+
}
|
|
1176
|
+
/**
|
|
1177
|
+
* Build the project. This transpiles/transforms/copies all files and moves them to the staging directory
|
|
1178
|
+
* @param options the list of options used to build the program
|
|
1179
|
+
*/
|
|
1180
|
+
async build(options) {
|
|
1181
|
+
//run a single build at a time
|
|
1182
|
+
await this.buildPipeline.run(async () => {
|
|
1183
|
+
var _a;
|
|
1184
|
+
const stagingDir = this.getStagingDir(options === null || options === void 0 ? void 0 : options.stagingDir);
|
|
1185
|
+
const event = await this.plugins.emitAsync('beforeBuildProgram', {
|
|
1186
|
+
program: this,
|
|
1187
|
+
editor: this.editor,
|
|
1188
|
+
files: (_a = options === null || options === void 0 ? void 0 : options.files) !== null && _a !== void 0 ? _a : Object.values(this.files)
|
|
1189
|
+
});
|
|
1190
|
+
//prepare the program (and files) for building
|
|
1191
|
+
event.files = await this.prepare(event.files);
|
|
1192
|
+
//stage the entire program
|
|
1193
|
+
const serializedFilesByFile = await this.serialize(event.files);
|
|
1194
|
+
await this.write(stagingDir, serializedFilesByFile);
|
|
1195
|
+
await this.plugins.emitAsync('afterBuildProgram', event);
|
|
1196
|
+
//undo all edits for the program
|
|
1197
|
+
this.editor.undoAll();
|
|
1198
|
+
//undo all edits for each file
|
|
1199
|
+
for (const file of event.files) {
|
|
1200
|
+
file.editor.undoAll();
|
|
1201
|
+
}
|
|
1017
1202
|
});
|
|
1018
|
-
astEditor.undoAll();
|
|
1019
1203
|
}
|
|
1020
1204
|
/**
|
|
1021
1205
|
* Find a list of files in the program that have a function with the given name (case INsensitive)
|
|
@@ -1090,6 +1274,7 @@ class Program {
|
|
|
1090
1274
|
* Get a map of the manifest information
|
|
1091
1275
|
*/
|
|
1092
1276
|
getManifest() {
|
|
1277
|
+
var _a, _b;
|
|
1093
1278
|
if (!this._manifest) {
|
|
1094
1279
|
//load the manifest file.
|
|
1095
1280
|
//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
|
|
@@ -1098,7 +1283,27 @@ class Program {
|
|
|
1098
1283
|
try {
|
|
1099
1284
|
//we only load this manifest once, so do it sync to improve speed downstream
|
|
1100
1285
|
contents = fsExtra.readFileSync(manifestPath, 'utf-8');
|
|
1101
|
-
|
|
1286
|
+
let parsedManifest = (0, Manifest_1.parseManifest)(contents);
|
|
1287
|
+
// Lift the bs_consts defined in the manifest
|
|
1288
|
+
let bsConsts = (0, Manifest_1.getBsConst)(parsedManifest, false);
|
|
1289
|
+
// Override or delete any bs_consts defined in the bs config
|
|
1290
|
+
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) {
|
|
1291
|
+
const value = this.options.manifest.bs_const[key];
|
|
1292
|
+
if (value === null) {
|
|
1293
|
+
bsConsts.delete(key);
|
|
1294
|
+
}
|
|
1295
|
+
else {
|
|
1296
|
+
bsConsts.set(key, value);
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
// convert the new list of bs consts back into a string for the rest of the down stream systems to use
|
|
1300
|
+
let constString = '';
|
|
1301
|
+
for (const [key, value] of bsConsts) {
|
|
1302
|
+
constString += `${constString !== '' ? ';' : ''}${key}=${value.toString()}`;
|
|
1303
|
+
}
|
|
1304
|
+
// Set the updated bs_const value
|
|
1305
|
+
parsedManifest.set('bs_const', constString);
|
|
1306
|
+
this._manifest = parsedManifest;
|
|
1102
1307
|
}
|
|
1103
1308
|
catch (err) {
|
|
1104
1309
|
this._manifest = new Map();
|
|
@@ -1107,16 +1312,29 @@ class Program {
|
|
|
1107
1312
|
return this._manifest;
|
|
1108
1313
|
}
|
|
1109
1314
|
dispose() {
|
|
1315
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1110
1316
|
this.plugins.emit('beforeProgramDispose', { program: this });
|
|
1111
1317
|
for (let filePath in this.files) {
|
|
1112
|
-
this.files[filePath].dispose();
|
|
1318
|
+
(_b = (_a = this.files[filePath]) === null || _a === void 0 ? void 0 : _a.dispose) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
1113
1319
|
}
|
|
1114
1320
|
for (let name in this.scopes) {
|
|
1115
|
-
this.scopes[name].dispose();
|
|
1321
|
+
(_d = (_c = this.scopes[name]) === null || _c === void 0 ? void 0 : _c.dispose) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
1116
1322
|
}
|
|
1117
|
-
this.globalScope.dispose();
|
|
1118
|
-
this.dependencyGraph.dispose();
|
|
1323
|
+
(_f = (_e = this.globalScope) === null || _e === void 0 ? void 0 : _e.dispose) === null || _f === void 0 ? void 0 : _f.call(_e);
|
|
1324
|
+
(_h = (_g = this.dependencyGraph) === null || _g === void 0 ? void 0 : _g.dispose) === null || _h === void 0 ? void 0 : _h.call(_g);
|
|
1119
1325
|
}
|
|
1120
1326
|
}
|
|
1121
1327
|
exports.Program = Program;
|
|
1328
|
+
class ProvideFileEventInternal {
|
|
1329
|
+
constructor(program, srcPath, destPath, data, fileFactory) {
|
|
1330
|
+
var _a;
|
|
1331
|
+
this.program = program;
|
|
1332
|
+
this.srcPath = srcPath;
|
|
1333
|
+
this.destPath = destPath;
|
|
1334
|
+
this.data = data;
|
|
1335
|
+
this.fileFactory = fileFactory;
|
|
1336
|
+
this.files = [];
|
|
1337
|
+
this.srcExtension = (_a = path.extname(srcPath)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1122
1340
|
//# sourceMappingURL=Program.js.map
|