brighterscript 0.66.0-alpha.6 → 0.66.0-alpha.8
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 +88 -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/AstValidationSegmenter.d.ts +25 -0
- package/dist/AstValidationSegmenter.js +150 -0
- package/dist/AstValidationSegmenter.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 +8 -1
- package/dist/DiagnosticMessages.js +30 -13
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/LanguageServer.js +7 -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 +107 -38
- package/dist/Program.js +502 -270
- 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 +26 -38
- package/dist/Scope.js +153 -174
- package/dist/Scope.js.map +1 -1
- package/dist/SymbolTable.d.ts +4 -1
- package/dist/SymbolTable.js +19 -7
- package/dist/SymbolTable.js.map +1 -1
- package/dist/XmlScope.d.ts +5 -4
- package/dist/XmlScope.js +16 -14
- 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/reflection.d.ts +9 -4
- package/dist/astUtils/reflection.js +23 -7
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/reflection.spec.js +2 -2
- package/dist/astUtils/reflection.spec.js.map +1 -1
- package/dist/astUtils/visitors.d.ts +14 -3
- package/dist/astUtils/visitors.js +22 -2
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/astUtils/visitors.spec.js +58 -7
- package/dist/astUtils/visitors.spec.js.map +1 -1
- package/dist/bscPlugin/BscPlugin.d.ts +10 -2
- package/dist/bscPlugin/BscPlugin.js +24 -4
- package/dist/bscPlugin/BscPlugin.js.map +1 -1
- package/dist/bscPlugin/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.map +1 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +7 -2
- package/dist/bscPlugin/completions/CompletionsProcessor.js +112 -44
- package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +212 -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 +10 -8
- package/dist/bscPlugin/hover/HoverProcessor.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.js +8 -3
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js +1 -1
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -1
- package/dist/bscPlugin/validation/ScopeValidator.d.ts +5 -9
- package/dist/bscPlugin/validation/ScopeValidator.js +214 -222
- package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
- package/dist/bscPlugin/validation/ScopeValidator.spec.js +669 -0
- 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 +241 -40
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +66 -16
- package/dist/files/BrsFile.js +330 -80
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +1134 -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 +1 -1
- package/dist/globalCallables.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +357 -89
- package/dist/interfaces.js +10 -2
- package/dist/interfaces.js.map +1 -1
- package/dist/lexer/Lexer.js +1 -1
- package/dist/lexer/TokenKind.d.ts +1 -0
- package/dist/lexer/TokenKind.js +4 -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 +2 -2
- package/dist/parser/Expression.js +23 -19
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +103 -0
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.js +61 -13
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.js +227 -1
- 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.d.ts +12 -5
- package/dist/parser/Statement.js +56 -26
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +16 -16
- 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/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 +90 -16
- 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 +35 -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 +20 -12
- 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 +98 -193
- package/dist/roku-types/index.d.ts +15 -11
- package/dist/types/ArrayType.d.ts +1 -1
- package/dist/types/ArrayType.js +4 -0
- package/dist/types/ArrayType.js.map +1 -1
- package/dist/types/ArrayType.spec.js +1 -1
- package/dist/types/ArrayType.spec.js.map +1 -1
- package/dist/types/AssociativeArrayType.d.ts +1 -1
- package/dist/types/AssociativeArrayType.js +1 -1
- package/dist/types/AssociativeArrayType.js.map +1 -1
- package/dist/types/BooleanType.d.ts +1 -1
- package/dist/types/BooleanType.js +2 -1
- package/dist/types/BooleanType.js.map +1 -1
- package/dist/types/BscType.d.ts +2 -2
- package/dist/types/BscType.js +30 -9
- package/dist/types/BscType.js.map +1 -1
- package/dist/types/BuiltInInterfaceAdder.d.ts +3 -0
- package/dist/types/BuiltInInterfaceAdder.js +37 -16
- package/dist/types/BuiltInInterfaceAdder.js.map +1 -1
- package/dist/types/BuiltInInterfaceAdder.spec.js +7 -0
- package/dist/types/BuiltInInterfaceAdder.spec.js.map +1 -1
- package/dist/types/ClassType.d.ts +4 -3
- package/dist/types/ClassType.js +6 -3
- 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 +1 -1
- package/dist/types/ComponentType.js +3 -0
- package/dist/types/ComponentType.js.map +1 -1
- package/dist/types/DoubleType.js +3 -1
- package/dist/types/DoubleType.js.map +1 -1
- package/dist/types/EnumType.d.ts +1 -1
- package/dist/types/EnumType.js +7 -2
- package/dist/types/EnumType.js.map +1 -1
- package/dist/types/FloatType.js +3 -1
- package/dist/types/FloatType.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.js +3 -1
- package/dist/types/IntegerType.js.map +1 -1
- package/dist/types/InterfaceType.d.ts +5 -4
- package/dist/types/InterfaceType.js +5 -12
- package/dist/types/InterfaceType.js.map +1 -1
- package/dist/types/InterfaceType.spec.js +23 -0
- package/dist/types/InterfaceType.spec.js.map +1 -1
- package/dist/types/LongIntegerType.js +3 -1
- 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 +1 -1
- package/dist/types/ReferenceType.js +40 -6
- package/dist/types/ReferenceType.js.map +1 -1
- package/dist/types/StringType.js +2 -2
- package/dist/types/StringType.js.map +1 -1
- package/dist/types/TypedFunctionType.d.ts +6 -1
- package/dist/types/TypedFunctionType.js +46 -16
- 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/UnionType.js +8 -0
- package/dist/types/UnionType.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 +3 -0
- package/dist/types/helpers.js +33 -1
- package/dist/types/helpers.js.map +1 -1
- package/dist/util.d.ts +25 -9
- package/dist/util.js +165 -72
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +2 -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/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,11 +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");
|
|
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");
|
|
39
40
|
const roku_types_1 = require("./roku-types");
|
|
40
41
|
const ComponentType_1 = require("./types/ComponentType");
|
|
41
42
|
const types_1 = require("./types");
|
|
42
43
|
const BuiltInInterfaceAdder_1 = require("./types/BuiltInInterfaceAdder");
|
|
43
|
-
const startOfSourcePkgPath = `source${path.sep}`;
|
|
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,6 +50,10 @@ class Program {
|
|
|
50
50
|
*/
|
|
51
51
|
options, logger, plugins) {
|
|
52
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();
|
|
53
57
|
/**
|
|
54
58
|
* A graph of all files and their dependencies.
|
|
55
59
|
* For example:
|
|
@@ -64,11 +68,21 @@ class Program {
|
|
|
64
68
|
* Should only be set from `this.validate()`
|
|
65
69
|
*/
|
|
66
70
|
this.diagnostics = [];
|
|
71
|
+
this.fileSymbolInformation = new Map();
|
|
67
72
|
/**
|
|
68
73
|
* A map of every file loaded into this program, indexed by its original file location
|
|
69
74
|
*/
|
|
70
75
|
this.files = {};
|
|
71
|
-
|
|
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();
|
|
72
86
|
this.scopes = {};
|
|
73
87
|
/**
|
|
74
88
|
* A map of every component currently loaded into the program, indexed by the component name.
|
|
@@ -81,6 +95,9 @@ class Program {
|
|
|
81
95
|
* Keeps a set of all the components that need to have their types updated during the current validation cycle
|
|
82
96
|
*/
|
|
83
97
|
this.componentSymbolsToUpdate = new Set();
|
|
98
|
+
this.lastValidationInfo = new Map();
|
|
99
|
+
this.getTranspiledFileContentsPipeline = new ActionPipeline_1.ActionPipeline();
|
|
100
|
+
this.buildPipeline = new ActionPipeline_1.ActionPipeline();
|
|
84
101
|
this.options = util_1.util.normalizeConfig(options);
|
|
85
102
|
this.logger = logger || new Logger_1.Logger(options.logLevel);
|
|
86
103
|
this.plugins = plugins || new PluginInterface_1.default([], { logger: this.logger });
|
|
@@ -89,6 +106,7 @@ class Program {
|
|
|
89
106
|
//normalize the root dir path
|
|
90
107
|
this.options.rootDir = util_1.util.getRootDir(this.options);
|
|
91
108
|
this.createGlobalScope();
|
|
109
|
+
this.fileFactory = new Factory_1.FileFactory(this);
|
|
92
110
|
}
|
|
93
111
|
createGlobalScope() {
|
|
94
112
|
//create the 'global' scope
|
|
@@ -98,6 +116,7 @@ class Program {
|
|
|
98
116
|
this.populateGlobalSymbolTable();
|
|
99
117
|
//hardcode the files list for global scope to only contain the global file
|
|
100
118
|
this.globalScope.getAllFiles = () => [globalCallables_1.globalFile];
|
|
119
|
+
globalCallables_1.globalFile.isValidated = true;
|
|
101
120
|
this.globalScope.validate();
|
|
102
121
|
//for now, disable validation of global scope because the global files have some duplicate method declarations
|
|
103
122
|
this.globalScope.getDiagnostics = () => [];
|
|
@@ -126,7 +145,7 @@ class Program {
|
|
|
126
145
|
this.globalScope.symbolTable.addSymbol(nodeName, { description: nodeData.description }, nodeType, SymbolTable_1.SymbolTypeFlag.typetime);
|
|
127
146
|
}
|
|
128
147
|
else {
|
|
129
|
-
nodeType = this.globalScope.symbolTable.getSymbolType(
|
|
148
|
+
nodeType = this.globalScope.symbolTable.getSymbolType(nodeName, { flags: SymbolTable_1.SymbolTypeFlag.typetime });
|
|
130
149
|
}
|
|
131
150
|
return nodeType;
|
|
132
151
|
}
|
|
@@ -168,6 +187,15 @@ class Program {
|
|
|
168
187
|
this.recursivelyAddNodeToSymbolTable(nodeData);
|
|
169
188
|
}
|
|
170
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);
|
|
198
|
+
}
|
|
171
199
|
/**
|
|
172
200
|
* The path to bslib.brs (the BrightScript runtime for certain BrighterScript features)
|
|
173
201
|
*/
|
|
@@ -182,7 +210,7 @@ class Program {
|
|
|
182
210
|
//default to the embedded version
|
|
183
211
|
}
|
|
184
212
|
else {
|
|
185
|
-
return
|
|
213
|
+
return `${this.options.bslibDestinationDir}${path.sep}bslib.brs`;
|
|
186
214
|
}
|
|
187
215
|
}
|
|
188
216
|
get bslibPrefix() {
|
|
@@ -203,7 +231,7 @@ class Program {
|
|
|
203
231
|
var _a;
|
|
204
232
|
if (componentName) {
|
|
205
233
|
//return the first compoment in the list with this name
|
|
206
|
-
//(components are ordered in this list by
|
|
234
|
+
//(components are ordered in this list by destPath to ensure consistency)
|
|
207
235
|
return (_a = this.components[componentName.toLowerCase()]) === null || _a === void 0 ? void 0 : _a[0];
|
|
208
236
|
}
|
|
209
237
|
else {
|
|
@@ -223,8 +251,8 @@ class Program {
|
|
|
223
251
|
scope: scope
|
|
224
252
|
});
|
|
225
253
|
this.components[key].sort((a, b) => {
|
|
226
|
-
const pathA = a.file.
|
|
227
|
-
const pathB = b.file.
|
|
254
|
+
const pathA = a.file.destPath.toLowerCase();
|
|
255
|
+
const pathB = b.file.destPath.toLowerCase();
|
|
228
256
|
if (pathA < pathB) {
|
|
229
257
|
return -1;
|
|
230
258
|
}
|
|
@@ -300,6 +328,7 @@ class Program {
|
|
|
300
328
|
//attach (or re-attach) the dependencyGraph for every component whose position changed
|
|
301
329
|
if (file.dependencyGraphIndex !== i) {
|
|
302
330
|
file.dependencyGraphIndex = i;
|
|
331
|
+
this.dependencyGraph.addOrReplace(file.dependencyGraphKey, file.dependencies);
|
|
303
332
|
file.attachDependencyGraph(this.dependencyGraph);
|
|
304
333
|
scope.attachDependencyGraph(this.dependencyGraph);
|
|
305
334
|
}
|
|
@@ -336,7 +365,7 @@ class Program {
|
|
|
336
365
|
//get the diagnostics from all unreferenced files
|
|
337
366
|
let unreferencedFiles = this.getUnreferencedFiles();
|
|
338
367
|
for (let file of unreferencedFiles) {
|
|
339
|
-
diagnostics.push(...file.
|
|
368
|
+
diagnostics.push(...file.diagnostics);
|
|
340
369
|
}
|
|
341
370
|
const filteredDiagnostics = this.logger.time(Logger_1.LogLevel.debug, ['filter diagnostics'], () => {
|
|
342
371
|
//filter out diagnostics based on our diagnostic filters
|
|
@@ -361,11 +390,9 @@ class Program {
|
|
|
361
390
|
hasFile(filePath, normalizePath = true) {
|
|
362
391
|
return !!this.getFile(filePath, normalizePath);
|
|
363
392
|
}
|
|
364
|
-
getPkgPath(...args) {
|
|
365
|
-
throw new Error('Not implemented');
|
|
366
|
-
}
|
|
367
393
|
/**
|
|
368
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"`
|
|
369
396
|
*/
|
|
370
397
|
getScopeByName(scopeName) {
|
|
371
398
|
if (!scopeName) {
|
|
@@ -394,8 +421,14 @@ class Program {
|
|
|
394
421
|
* Update internal maps with this file reference
|
|
395
422
|
*/
|
|
396
423
|
assignFile(file) {
|
|
424
|
+
const fileAddEvent = {
|
|
425
|
+
file: file,
|
|
426
|
+
program: this
|
|
427
|
+
};
|
|
428
|
+
this.plugins.emit('beforeFileAdd', fileAddEvent);
|
|
397
429
|
this.files[file.srcPath.toLowerCase()] = file;
|
|
398
|
-
this.
|
|
430
|
+
this.destMap.set(file.destPath.toLowerCase(), file);
|
|
431
|
+
this.plugins.emit('afterFileAdd', fileAddEvent);
|
|
399
432
|
return file;
|
|
400
433
|
}
|
|
401
434
|
/**
|
|
@@ -403,104 +436,102 @@ class Program {
|
|
|
403
436
|
*/
|
|
404
437
|
unassignFile(file) {
|
|
405
438
|
delete this.files[file.srcPath.toLowerCase()];
|
|
406
|
-
|
|
439
|
+
this.destMap.delete(file.destPath.toLowerCase());
|
|
407
440
|
return file;
|
|
408
441
|
}
|
|
409
|
-
setFile(fileParam,
|
|
442
|
+
setFile(fileParam, fileData) {
|
|
410
443
|
//normalize the file paths
|
|
411
|
-
const { srcPath,
|
|
444
|
+
const { srcPath, destPath } = this.getPaths(fileParam, this.options.rootDir);
|
|
412
445
|
let file = this.logger.time(Logger_1.LogLevel.debug, ['Program.setFile()', chalk_1.default.green(srcPath)], () => {
|
|
446
|
+
var _a, _b, _c;
|
|
413
447
|
//if the file is already loaded, remove it
|
|
414
448
|
if (this.hasFile(srcPath)) {
|
|
415
|
-
this.removeFile(srcPath);
|
|
449
|
+
this.removeFile(srcPath, true, true);
|
|
416
450
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
source: fileContents
|
|
431
|
-
};
|
|
432
|
-
this.plugins.emit('beforeFileParse', beforeFileParseEvent);
|
|
433
|
-
this.logger.time(Logger_1.LogLevel.debug, ['parse', chalk_1.default.green(srcPath)], () => {
|
|
434
|
-
brsFile.parse(beforeFileParseEvent.source);
|
|
435
|
-
});
|
|
436
|
-
//notify plugins that this file has finished parsing
|
|
437
|
-
this.plugins.emit('afterFileParse', {
|
|
438
|
-
program: this,
|
|
439
|
-
file: brsFile
|
|
440
|
-
});
|
|
441
|
-
file = brsFile;
|
|
442
|
-
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
|
+
}));
|
|
443
464
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
program: this,
|
|
453
|
-
srcPath: srcPath,
|
|
454
|
-
source: fileContents
|
|
455
|
-
};
|
|
456
|
-
this.plugins.emit('beforeFileParse', event);
|
|
457
|
-
this.logger.time(Logger_1.LogLevel.debug, ['parse', chalk_1.default.green(srcPath)], () => {
|
|
458
|
-
xmlFile.parse(event.source);
|
|
459
|
-
});
|
|
460
|
-
//notify plugins that this file has finished parsing
|
|
461
|
-
this.plugins.emit('afterFileParse', {
|
|
462
|
-
program: this,
|
|
463
|
-
file: xmlFile
|
|
464
|
-
});
|
|
465
|
-
file = xmlFile;
|
|
466
|
-
//create a new scope for this xml file
|
|
467
|
-
let scope = new XmlScope_1.XmlScope(xmlFile, this);
|
|
468
|
-
this.addScope(scope);
|
|
469
|
-
//register this component now that we have parsed it and know its component name
|
|
470
|
-
this.registerComponent(xmlFile, scope);
|
|
471
|
-
//notify plugins that the scope is created and the component is registered
|
|
472
|
-
this.plugins.emit('afterScopeCreate', {
|
|
473
|
-
program: this,
|
|
474
|
-
scope: scope
|
|
475
|
-
});
|
|
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
|
+
})))}`);
|
|
476
473
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
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
|
+
}
|
|
485
516
|
}
|
|
486
|
-
return
|
|
517
|
+
return primaryFile;
|
|
487
518
|
});
|
|
488
519
|
return file;
|
|
489
520
|
}
|
|
490
521
|
/**
|
|
491
|
-
* Given a srcPath, a
|
|
522
|
+
* Given a srcPath, a destPath, or both, resolve whichever is missing, relative to rootDir.
|
|
492
523
|
* @param fileParam an object representing file paths
|
|
493
524
|
* @param rootDir must be a pre-normalized path
|
|
494
525
|
*/
|
|
495
526
|
getPaths(fileParam, rootDir) {
|
|
496
527
|
let srcPath;
|
|
497
|
-
let
|
|
528
|
+
let destPath;
|
|
498
529
|
assert.ok(fileParam, 'fileParam is required');
|
|
499
|
-
//lift the
|
|
530
|
+
//lift the path vars from the incoming param
|
|
500
531
|
if (typeof fileParam === 'string') {
|
|
501
532
|
fileParam = this.removePkgPrefix(fileParam);
|
|
502
533
|
srcPath = (0, util_1.standardizePath) `${path.resolve(rootDir, fileParam)}`;
|
|
503
|
-
|
|
534
|
+
destPath = (0, util_1.standardizePath) `${util_1.util.replaceCaseInsensitive(srcPath, rootDir, '')}`;
|
|
504
535
|
}
|
|
505
536
|
else {
|
|
506
537
|
let param = fileParam;
|
|
@@ -511,30 +542,30 @@ class Program {
|
|
|
511
542
|
srcPath = (0, util_1.standardizePath) `${param.srcPath}`;
|
|
512
543
|
}
|
|
513
544
|
if (param.dest) {
|
|
514
|
-
|
|
545
|
+
destPath = (0, util_1.standardizePath) `${this.removePkgPrefix(param.dest)}`;
|
|
515
546
|
}
|
|
516
547
|
if (param.pkgPath) {
|
|
517
|
-
|
|
548
|
+
destPath = (0, util_1.standardizePath) `${this.removePkgPrefix(param.pkgPath)}`;
|
|
518
549
|
}
|
|
519
550
|
}
|
|
520
|
-
//if there's no srcPath, use the
|
|
551
|
+
//if there's no srcPath, use the destPath to build an absolute srcPath
|
|
521
552
|
if (!srcPath) {
|
|
522
|
-
srcPath = (0, util_1.standardizePath) `${rootDir}/${
|
|
553
|
+
srcPath = (0, util_1.standardizePath) `${rootDir}/${destPath}`;
|
|
523
554
|
}
|
|
524
555
|
//coerce srcPath to an absolute path
|
|
525
556
|
if (!path.isAbsolute(srcPath)) {
|
|
526
557
|
srcPath = util_1.util.standardizePath(srcPath);
|
|
527
558
|
}
|
|
528
|
-
//if
|
|
529
|
-
if (!
|
|
530
|
-
|
|
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, '')}`;
|
|
531
562
|
}
|
|
532
563
|
assert.ok(srcPath, 'fileEntry.src is required');
|
|
533
|
-
assert.ok(
|
|
564
|
+
assert.ok(destPath, 'fileEntry.dest is required');
|
|
534
565
|
return {
|
|
535
566
|
srcPath: srcPath,
|
|
536
|
-
//remove leading slash
|
|
537
|
-
|
|
567
|
+
//remove leading slash
|
|
568
|
+
destPath: destPath.replace(/^[\/\\]+/, '')
|
|
538
569
|
};
|
|
539
570
|
}
|
|
540
571
|
/**
|
|
@@ -543,6 +574,18 @@ class Program {
|
|
|
543
574
|
removePkgPrefix(path) {
|
|
544
575
|
return path.replace(/^pkg:\//i, '');
|
|
545
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
|
+
}
|
|
546
589
|
/**
|
|
547
590
|
* Ensure source scope is created.
|
|
548
591
|
* Note: automatically called internally, and no-op if it exists already.
|
|
@@ -570,46 +613,58 @@ class Program {
|
|
|
570
613
|
}
|
|
571
614
|
/**
|
|
572
615
|
* Remove a file from the program
|
|
573
|
-
* @param filePath can be a srcPath, a
|
|
616
|
+
* @param filePath can be a srcPath, a destPath, or a destPath with leading `pkg:/`
|
|
574
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
|
|
575
618
|
*/
|
|
576
|
-
removeFile(filePath, normalizePath = true) {
|
|
619
|
+
removeFile(filePath, normalizePath = true, keepSymbolInformation = false) {
|
|
620
|
+
var _a, _b, _c, _d;
|
|
577
621
|
this.logger.debug('Program.removeFile()', filePath);
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
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);
|
|
585
632
|
//if there is a scope named the same as this file's path, remove it (i.e. xml scopes)
|
|
586
|
-
let scope = this.scopes[file.
|
|
633
|
+
let scope = this.scopes[file.destPath];
|
|
587
634
|
if (scope) {
|
|
588
635
|
const scopeDisposeEvent = {
|
|
589
636
|
program: this,
|
|
590
637
|
scope: scope
|
|
591
638
|
};
|
|
592
639
|
this.plugins.emit('beforeScopeDispose', scopeDisposeEvent);
|
|
640
|
+
this.plugins.emit('onScopeDispose', scopeDisposeEvent);
|
|
593
641
|
scope.dispose();
|
|
594
642
|
//notify dependencies of this scope that it has been removed
|
|
595
643
|
this.dependencyGraph.remove(scope.dependencyGraphKey);
|
|
596
|
-
delete this.scopes[file.
|
|
644
|
+
delete this.scopes[file.destPath];
|
|
597
645
|
this.plugins.emit('afterScopeDispose', scopeDisposeEvent);
|
|
598
646
|
}
|
|
599
647
|
//remove the file from the program
|
|
600
648
|
this.unassignFile(file);
|
|
601
649
|
this.dependencyGraph.remove(file.dependencyGraphKey);
|
|
602
650
|
//if this is a pkg:/source file, notify the `source` scope that it has changed
|
|
603
|
-
if (
|
|
651
|
+
if (this.isSourceBrsFile(file)) {
|
|
604
652
|
this.dependencyGraph.removeDependency('scope:source', file.dependencyGraphKey);
|
|
653
|
+
if (!keepSymbolInformation) {
|
|
654
|
+
this.fileSymbolInformation.delete(file.pkgPath);
|
|
655
|
+
}
|
|
605
656
|
}
|
|
606
657
|
//if this is a component, remove it from our components map
|
|
607
658
|
if ((0, reflection_1.isXmlFile)(file)) {
|
|
608
659
|
this.unregisterComponent(file);
|
|
609
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
|
+
}
|
|
610
665
|
//dispose file
|
|
611
|
-
file === null || file === void 0 ? void 0 : file.dispose();
|
|
612
|
-
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);
|
|
613
668
|
}
|
|
614
669
|
}
|
|
615
670
|
/**
|
|
@@ -617,12 +672,15 @@ class Program {
|
|
|
617
672
|
*/
|
|
618
673
|
validate() {
|
|
619
674
|
this.logger.time(Logger_1.LogLevel.log, ['Validating project'], () => {
|
|
675
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
620
676
|
this.diagnostics = [];
|
|
621
677
|
const programValidateEvent = {
|
|
622
678
|
program: this
|
|
623
679
|
};
|
|
624
680
|
this.plugins.emit('beforeProgramValidate', programValidateEvent);
|
|
681
|
+
this.plugins.emit('onProgramValidate', programValidateEvent);
|
|
625
682
|
//validate every file
|
|
683
|
+
const brsFilesValidated = [];
|
|
626
684
|
for (const file of Object.values(this.files)) {
|
|
627
685
|
//for every unvalidated file, validate it
|
|
628
686
|
if (!file.isValidated) {
|
|
@@ -634,9 +692,80 @@ class Program {
|
|
|
634
692
|
//emit an event to allow plugins to contribute to the file validation process
|
|
635
693
|
this.plugins.emit('onFileValidate', validateFileEvent);
|
|
636
694
|
file.isValidated = true;
|
|
695
|
+
if ((0, reflection_1.isBrsFile)(file)) {
|
|
696
|
+
brsFilesValidated.push(file);
|
|
697
|
+
}
|
|
637
698
|
this.plugins.emit('afterFileValidate', validateFileEvent);
|
|
638
699
|
}
|
|
639
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();
|
|
640
769
|
// Build component types for any component that changes
|
|
641
770
|
this.logger.time(Logger_1.LogLevel.info, ['Build component types'], () => {
|
|
642
771
|
for (let { componentKey, componentName } of this.componentSymbolsToUpdate) {
|
|
@@ -644,16 +773,37 @@ class Program {
|
|
|
644
773
|
}
|
|
645
774
|
this.componentSymbolsToUpdate.clear();
|
|
646
775
|
});
|
|
776
|
+
const changedSymbolsMapArr = brsFilesValidated === null || brsFilesValidated === void 0 ? void 0 : brsFilesValidated.map(f => {
|
|
777
|
+
if ((0, reflection_1.isBrsFile)(f)) {
|
|
778
|
+
return f.providedSymbols.changes;
|
|
779
|
+
}
|
|
780
|
+
return null;
|
|
781
|
+
}).filter(x => x);
|
|
782
|
+
const changedSymbols = new Map();
|
|
783
|
+
for (const flag of [SymbolTable_1.SymbolTypeFlag.runtime, SymbolTable_1.SymbolTypeFlag.typetime]) {
|
|
784
|
+
const changedSymbolsSetArr = changedSymbolsMapArr.map(symMap => symMap.get(flag));
|
|
785
|
+
changedSymbols.set(flag, new Set(...changedSymbolsSetArr));
|
|
786
|
+
}
|
|
647
787
|
this.logger.time(Logger_1.LogLevel.info, ['Validate all scopes'], () => {
|
|
648
788
|
for (let scopeName in this.scopes) {
|
|
649
789
|
let scope = this.scopes[scopeName];
|
|
650
|
-
scope.validate();
|
|
790
|
+
scope.validate({ changedFiles: brsFilesValidated, changedSymbols: changedSymbols });
|
|
651
791
|
}
|
|
652
792
|
});
|
|
653
793
|
this.detectDuplicateComponentNames();
|
|
654
794
|
this.plugins.emit('afterProgramValidate', programValidateEvent);
|
|
655
795
|
});
|
|
656
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
|
+
}
|
|
657
807
|
/**
|
|
658
808
|
* Flag all duplicate component names
|
|
659
809
|
*/
|
|
@@ -706,12 +856,13 @@ class Program {
|
|
|
706
856
|
getFile(filePath, normalizePath = true) {
|
|
707
857
|
if (typeof filePath !== 'string') {
|
|
708
858
|
return undefined;
|
|
859
|
+
//is the path absolute (or the `virtual:` prefix)
|
|
709
860
|
}
|
|
710
|
-
else if (
|
|
861
|
+
else if (/^(?:(?:virtual:[\/\\])|(?:\w:)|(?:[\/\\]))/gmi.exec(filePath)) {
|
|
711
862
|
return this.files[(normalizePath ? util_1.util.standardizePath(filePath) : filePath).toLowerCase()];
|
|
712
863
|
}
|
|
713
864
|
else {
|
|
714
|
-
return this.
|
|
865
|
+
return this.destMap.get((normalizePath ? util_1.util.standardizePath(filePath) : filePath).toLowerCase());
|
|
715
866
|
}
|
|
716
867
|
}
|
|
717
868
|
/**
|
|
@@ -753,7 +904,8 @@ class Program {
|
|
|
753
904
|
//look through all files in scope for matches
|
|
754
905
|
for (const scope of this.getScopesForFile(originFile)) {
|
|
755
906
|
for (const file of scope.getAllFiles()) {
|
|
756
|
-
|
|
907
|
+
//skip non-brs files, or files we've already processed
|
|
908
|
+
if (!(0, reflection_1.isBrsFile)(file) || filesSearched.has(file)) {
|
|
757
909
|
continue;
|
|
758
910
|
}
|
|
759
911
|
filesSearched.add(file);
|
|
@@ -786,7 +938,8 @@ class Program {
|
|
|
786
938
|
}
|
|
787
939
|
//look through all files in scope for matches
|
|
788
940
|
for (const file of scope.getOwnFiles()) {
|
|
789
|
-
|
|
941
|
+
//skip non-brs files, or files we've already processed
|
|
942
|
+
if (!(0, reflection_1.isBrsFile)(file) || filesSearched.has(file)) {
|
|
790
943
|
continue;
|
|
791
944
|
}
|
|
792
945
|
filesSearched.add(file);
|
|
@@ -935,10 +1088,12 @@ class Program {
|
|
|
935
1088
|
getReferences(srcPath, position) {
|
|
936
1089
|
//find the file
|
|
937
1090
|
let file = this.getFile(srcPath);
|
|
938
|
-
if (
|
|
1091
|
+
if ((0, reflection_1.isBrsFile)(file) || (0, reflection_1.isXmlFile)(file)) {
|
|
1092
|
+
return file.getReferences(position);
|
|
1093
|
+
}
|
|
1094
|
+
else {
|
|
939
1095
|
return null;
|
|
940
1096
|
}
|
|
941
|
-
return file.getReferences(position);
|
|
942
1097
|
}
|
|
943
1098
|
/**
|
|
944
1099
|
* Transpile a single file and get the result as a string.
|
|
@@ -949,168 +1104,211 @@ class Program {
|
|
|
949
1104
|
* @param filePath can be a srcPath or a destPath
|
|
950
1105
|
*/
|
|
951
1106
|
async getTranspiledFileContents(filePath) {
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
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
|
+
});
|
|
958
1147
|
}
|
|
1148
|
+
finally {
|
|
1149
|
+
this.plugins.remove(plugin);
|
|
1150
|
+
}
|
|
1151
|
+
return result;
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
1154
|
+
/**
|
|
1155
|
+
* Get the absolute output path for a file
|
|
1156
|
+
*/
|
|
1157
|
+
getOutputPath(file, stagingDir = this.getStagingDir()) {
|
|
1158
|
+
return (0, util_1.standardizePath) `${stagingDir}/${file.pkgPath}`;
|
|
1159
|
+
}
|
|
1160
|
+
getStagingDir(stagingDir) {
|
|
1161
|
+
var _a, _b;
|
|
1162
|
+
let result = (_a = stagingDir !== null && stagingDir !== void 0 ? stagingDir : this.options.stagingDir) !== null && _a !== void 0 ? _a : this.options.stagingDir;
|
|
1163
|
+
if (!result) {
|
|
1164
|
+
result = roku_deploy_1.rokuDeploy.getOptions(this.options).stagingDir;
|
|
959
1165
|
}
|
|
960
|
-
|
|
961
|
-
const result = this._getTranspiledFileContents(this.getFile(filePath));
|
|
962
|
-
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 : '/')}`;
|
|
963
1167
|
return result;
|
|
964
1168
|
}
|
|
965
1169
|
/**
|
|
966
|
-
*
|
|
967
|
-
*
|
|
1170
|
+
* Prepare the program for building
|
|
1171
|
+
* @param files the list of files that should be prepared
|
|
968
1172
|
*/
|
|
969
|
-
|
|
970
|
-
const
|
|
971
|
-
this.plugins.emit('beforeFileTranspile', {
|
|
1173
|
+
async prepare(files) {
|
|
1174
|
+
const programEvent = {
|
|
972
1175
|
program: this,
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
editor: editor
|
|
976
|
-
});
|
|
977
|
-
//if we have any edits, assume the file needs to be transpiled
|
|
978
|
-
if (editor.hasChanges) {
|
|
979
|
-
//use the `editor` because it'll track the previous value for us and revert later on
|
|
980
|
-
editor.setProperty(file, 'needsTranspiled', true);
|
|
981
|
-
}
|
|
982
|
-
//transpile the file
|
|
983
|
-
const result = file.transpile();
|
|
984
|
-
//generate the typedef if enabled
|
|
985
|
-
let typedef;
|
|
986
|
-
if ((0, reflection_1.isBrsFile)(file) && this.options.emitDefinitions) {
|
|
987
|
-
typedef = file.getTypedef();
|
|
988
|
-
}
|
|
989
|
-
const event = {
|
|
990
|
-
program: this,
|
|
991
|
-
file: file,
|
|
992
|
-
outputPath: outputPath,
|
|
993
|
-
editor: editor,
|
|
994
|
-
code: result.code,
|
|
995
|
-
map: result.map,
|
|
996
|
-
typedef: typedef
|
|
997
|
-
};
|
|
998
|
-
this.plugins.emit('afterFileTranspile', event);
|
|
999
|
-
//undo all `editor` edits that may have been applied to this file.
|
|
1000
|
-
editor.undoAll();
|
|
1001
|
-
return {
|
|
1002
|
-
srcPath: file.srcPath,
|
|
1003
|
-
pkgPath: file.pkgPath,
|
|
1004
|
-
code: event.code,
|
|
1005
|
-
map: event.map,
|
|
1006
|
-
typedef: event.typedef
|
|
1176
|
+
editor: this.editor,
|
|
1177
|
+
files: files
|
|
1007
1178
|
};
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
return collection;
|
|
1014
|
-
}, {});
|
|
1015
|
-
const getOutputPath = (file) => {
|
|
1016
|
-
let filePathObj = mappedFileEntries[(0, util_1.standardizePath) `${file.srcPath}`];
|
|
1017
|
-
if (!filePathObj) {
|
|
1018
|
-
//this file has been added in-memory, from a plugin, for example
|
|
1019
|
-
filePathObj = {
|
|
1020
|
-
//add an interpolated src path (since it doesn't actually exist in memory)
|
|
1021
|
-
src: `bsc:/${file.pkgPath}`,
|
|
1022
|
-
dest: file.pkgPath
|
|
1023
|
-
};
|
|
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();
|
|
1024
1184
|
}
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
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
|
+
}
|
|
1196
|
+
});
|
|
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,
|
|
1033
1208
|
file: file,
|
|
1034
|
-
|
|
1209
|
+
editor: file.editor,
|
|
1210
|
+
outputPath: this.getOutputPath(file, stagingDir)
|
|
1035
1211
|
};
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
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);
|
|
1217
|
+
}
|
|
1218
|
+
await this.plugins.emitAsync('afterPrepareProgram', programEvent);
|
|
1219
|
+
return files;
|
|
1220
|
+
}
|
|
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
|
|
1039
1230
|
});
|
|
1040
|
-
|
|
1041
|
-
this.plugins.emit('beforeProgramTranspile', {
|
|
1231
|
+
await this.plugins.emitAsync('onSerializeProgram', {
|
|
1042
1232
|
program: this,
|
|
1043
|
-
|
|
1044
|
-
|
|
1233
|
+
files: files,
|
|
1234
|
+
result: allFiles
|
|
1045
1235
|
});
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
astEditor: astEditor
|
|
1050
|
-
};
|
|
1051
|
-
}
|
|
1052
|
-
async transpile(fileEntries, stagingDir) {
|
|
1053
|
-
const { entries, getOutputPath, astEditor } = this.beforeProgramTranspile(fileEntries, stagingDir);
|
|
1054
|
-
const processedFiles = new Set();
|
|
1055
|
-
const transpileFile = async (srcPath, outputPath) => {
|
|
1056
|
-
//find the file in the program
|
|
1057
|
-
const file = this.getFile(srcPath);
|
|
1058
|
-
//mark this file as processed so we don't process it more than once
|
|
1059
|
-
processedFiles.add(outputPath === null || outputPath === void 0 ? void 0 : outputPath.toLowerCase());
|
|
1060
|
-
//skip transpiling typedef files
|
|
1061
|
-
if ((0, reflection_1.isBrsFile)(file) && file.isTypedef) {
|
|
1062
|
-
return;
|
|
1063
|
-
}
|
|
1064
|
-
const fileTranspileResult = this._getTranspiledFileContents(file, outputPath);
|
|
1065
|
-
//make sure the full dir path exists
|
|
1066
|
-
await fsExtra.ensureDir(path.dirname(outputPath));
|
|
1067
|
-
if (await fsExtra.pathExists(outputPath)) {
|
|
1068
|
-
throw new Error(`Error while transpiling "${file.srcPath}". A file already exists at "${outputPath}" and will not be overwritten.`);
|
|
1069
|
-
}
|
|
1070
|
-
const writeMapPromise = fileTranspileResult.map ? fsExtra.writeFile(`${outputPath}.map`, fileTranspileResult.map.toString()) : null;
|
|
1071
|
-
await Promise.all([
|
|
1072
|
-
fsExtra.writeFile(outputPath, fileTranspileResult.code),
|
|
1073
|
-
writeMapPromise
|
|
1074
|
-
]);
|
|
1075
|
-
if (fileTranspileResult.typedef) {
|
|
1076
|
-
const typedefPath = outputPath.replace(/\.brs$/i, '.d.bs');
|
|
1077
|
-
await fsExtra.writeFile(typedefPath, fileTranspileResult.typedef);
|
|
1078
|
-
}
|
|
1079
|
-
};
|
|
1080
|
-
let promises = entries.map(async (entry) => {
|
|
1081
|
-
var _a;
|
|
1082
|
-
return transpileFile((_a = entry === null || entry === void 0 ? void 0 : entry.file) === null || _a === void 0 ? void 0 : _a.srcPath, entry.outputPath);
|
|
1236
|
+
//sort the entries to make transpiling more deterministic
|
|
1237
|
+
files = serializeProgramEvent.files.sort((a, b) => {
|
|
1238
|
+
return a.srcPath < b.srcPath ? -1 : 1;
|
|
1083
1239
|
});
|
|
1084
|
-
//
|
|
1085
|
-
|
|
1086
|
-
|
|
1240
|
+
// serialize each file
|
|
1241
|
+
for (const file of files) {
|
|
1242
|
+
const event = {
|
|
1243
|
+
program: this,
|
|
1244
|
+
file: file,
|
|
1245
|
+
result: allFiles
|
|
1246
|
+
};
|
|
1247
|
+
await this.plugins.emitAsync('beforeSerializeFile', event);
|
|
1248
|
+
await this.plugins.emitAsync('serializeFile', event);
|
|
1249
|
+
await this.plugins.emitAsync('afterSerializeFile', event);
|
|
1087
1250
|
}
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
//this is a new file
|
|
1095
|
-
const outputPath = getOutputPath(file);
|
|
1096
|
-
if (!processedFiles.has(outputPath === null || outputPath === void 0 ? void 0 : outputPath.toLowerCase())) {
|
|
1097
|
-
promises.push(transpileFile(file === null || file === void 0 ? void 0 : file.srcPath, outputPath));
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
if (promises.length > 0) {
|
|
1101
|
-
this.logger.info(`Transpiling ${promises.length} new files`);
|
|
1102
|
-
await Promise.all(promises);
|
|
1103
|
-
}
|
|
1104
|
-
} while (promises.length > 0);
|
|
1105
|
-
this.afterProgramTranspile(entries, astEditor);
|
|
1251
|
+
this.plugins.emit('afterSerializeProgram', {
|
|
1252
|
+
program: this,
|
|
1253
|
+
files: files,
|
|
1254
|
+
result: allFiles
|
|
1255
|
+
});
|
|
1256
|
+
return allFiles;
|
|
1106
1257
|
}
|
|
1107
|
-
|
|
1108
|
-
|
|
1258
|
+
/**
|
|
1259
|
+
* Write the entire project to disk
|
|
1260
|
+
*/
|
|
1261
|
+
async write(stagingDir, files) {
|
|
1262
|
+
const programEvent = await this.plugins.emitAsync('beforeWriteProgram', {
|
|
1109
1263
|
program: this,
|
|
1110
|
-
|
|
1111
|
-
|
|
1264
|
+
files: files,
|
|
1265
|
+
stagingDir: stagingDir
|
|
1266
|
+
});
|
|
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);
|
|
1284
|
+
}
|
|
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
|
+
}
|
|
1112
1311
|
});
|
|
1113
|
-
astEditor.undoAll();
|
|
1114
1312
|
}
|
|
1115
1313
|
/**
|
|
1116
1314
|
* Find a list of files in the program that have a function with the given name (case INsensitive)
|
|
@@ -1185,6 +1383,7 @@ class Program {
|
|
|
1185
1383
|
* Get a map of the manifest information
|
|
1186
1384
|
*/
|
|
1187
1385
|
getManifest() {
|
|
1386
|
+
var _a, _b;
|
|
1188
1387
|
if (!this._manifest) {
|
|
1189
1388
|
//load the manifest file.
|
|
1190
1389
|
//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
|
|
@@ -1193,7 +1392,27 @@ class Program {
|
|
|
1193
1392
|
try {
|
|
1194
1393
|
//we only load this manifest once, so do it sync to improve speed downstream
|
|
1195
1394
|
contents = fsExtra.readFileSync(manifestPath, 'utf-8');
|
|
1196
|
-
|
|
1395
|
+
let parsedManifest = (0, Manifest_1.parseManifest)(contents);
|
|
1396
|
+
// Lift the bs_consts defined in the manifest
|
|
1397
|
+
let bsConsts = (0, Manifest_1.getBsConst)(parsedManifest, false);
|
|
1398
|
+
// Override or delete any bs_consts defined in the bs config
|
|
1399
|
+
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) {
|
|
1400
|
+
const value = this.options.manifest.bs_const[key];
|
|
1401
|
+
if (value === null) {
|
|
1402
|
+
bsConsts.delete(key);
|
|
1403
|
+
}
|
|
1404
|
+
else {
|
|
1405
|
+
bsConsts.set(key, value);
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
// convert the new list of bs consts back into a string for the rest of the down stream systems to use
|
|
1409
|
+
let constString = '';
|
|
1410
|
+
for (const [key, value] of bsConsts) {
|
|
1411
|
+
constString += `${constString !== '' ? ';' : ''}${key}=${value.toString()}`;
|
|
1412
|
+
}
|
|
1413
|
+
// Set the updated bs_const value
|
|
1414
|
+
parsedManifest.set('bs_const', constString);
|
|
1415
|
+
this._manifest = parsedManifest;
|
|
1197
1416
|
}
|
|
1198
1417
|
catch (err) {
|
|
1199
1418
|
this._manifest = new Map();
|
|
@@ -1202,16 +1421,29 @@ class Program {
|
|
|
1202
1421
|
return this._manifest;
|
|
1203
1422
|
}
|
|
1204
1423
|
dispose() {
|
|
1424
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1205
1425
|
this.plugins.emit('beforeProgramDispose', { program: this });
|
|
1206
1426
|
for (let filePath in this.files) {
|
|
1207
|
-
this.files[filePath].dispose();
|
|
1427
|
+
(_b = (_a = this.files[filePath]) === null || _a === void 0 ? void 0 : _a.dispose) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
1208
1428
|
}
|
|
1209
1429
|
for (let name in this.scopes) {
|
|
1210
|
-
this.scopes[name].dispose();
|
|
1430
|
+
(_d = (_c = this.scopes[name]) === null || _c === void 0 ? void 0 : _c.dispose) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
1211
1431
|
}
|
|
1212
|
-
this.globalScope.dispose();
|
|
1213
|
-
this.dependencyGraph.dispose();
|
|
1432
|
+
(_f = (_e = this.globalScope) === null || _e === void 0 ? void 0 : _e.dispose) === null || _f === void 0 ? void 0 : _f.call(_e);
|
|
1433
|
+
(_h = (_g = this.dependencyGraph) === null || _g === void 0 ? void 0 : _g.dispose) === null || _h === void 0 ? void 0 : _h.call(_g);
|
|
1214
1434
|
}
|
|
1215
1435
|
}
|
|
1216
1436
|
exports.Program = Program;
|
|
1437
|
+
class ProvideFileEventInternal {
|
|
1438
|
+
constructor(program, srcPath, destPath, data, fileFactory) {
|
|
1439
|
+
var _a;
|
|
1440
|
+
this.program = program;
|
|
1441
|
+
this.srcPath = srcPath;
|
|
1442
|
+
this.destPath = destPath;
|
|
1443
|
+
this.data = data;
|
|
1444
|
+
this.fileFactory = fileFactory;
|
|
1445
|
+
this.files = [];
|
|
1446
|
+
this.srcExtension = (_a = path.extname(srcPath)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1217
1449
|
//# sourceMappingURL=Program.js.map
|