brighterscript 0.43.0 → 0.45.1
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 +37 -0
- package/dist/Cache.d.ts +3 -8
- package/dist/Cache.js +9 -14
- package/dist/Cache.js.map +1 -1
- package/dist/DiagnosticMessages.d.ts +21 -1
- package/dist/DiagnosticMessages.js +20 -0
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/LanguageServer.d.ts +1 -6
- package/dist/LanguageServer.js +3 -3
- package/dist/LanguageServer.js.map +1 -1
- package/dist/PluginInterface.d.ts +3 -3
- package/dist/PluginInterface.js +3 -0
- package/dist/PluginInterface.js.map +1 -1
- package/dist/Program.d.ts +67 -24
- package/dist/Program.js +155 -88
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.js +3 -3
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +16 -10
- package/dist/Scope.js +28 -1
- package/dist/Scope.js.map +1 -1
- package/dist/XmlScope.d.ts +3 -3
- package/dist/astUtils/AstEditor.d.ts +6 -0
- package/dist/astUtils/AstEditor.js +10 -0
- package/dist/astUtils/AstEditor.js.map +1 -1
- package/dist/astUtils/AstEditor.spec.js +37 -0
- package/dist/astUtils/AstEditor.spec.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +3 -1
- package/dist/astUtils/reflection.js +10 -2
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/visitors.d.ts +3 -1
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/astUtils/visitors.spec.js +6 -6
- package/dist/astUtils/visitors.spec.js.map +1 -1
- package/dist/bscPlugin/BscPlugin.d.ts +4 -1
- package/dist/bscPlugin/BscPlugin.js +21 -2
- package/dist/bscPlugin/BscPlugin.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +18 -16
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +9 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +97 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
- package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.d.ts → BrsFileSemanticTokensProcessor.spec.d.ts} +0 -0
- package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.js → BrsFileSemanticTokensProcessor.spec.js} +32 -4
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +8 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +36 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -0
- package/dist/bscPlugin/validation/BrsFileValidator.d.ts +9 -0
- package/dist/bscPlugin/validation/BrsFileValidator.js +66 -0
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
- package/dist/bscPlugin/validation/ScopeValidator.d.ts +11 -0
- package/dist/bscPlugin/validation/ScopeValidator.js +94 -0
- package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
- package/dist/diagnosticUtils.js +3 -3
- package/dist/diagnosticUtils.js.map +1 -1
- package/dist/files/BrsFile.Class.spec.js +47 -47
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +16 -3
- package/dist/files/BrsFile.js +112 -30
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +194 -95
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/files/XmlFile.d.ts +10 -5
- package/dist/files/XmlFile.js +6 -1
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/XmlFile.spec.js +83 -81
- package/dist/files/XmlFile.spec.js.map +1 -1
- package/dist/files/tests/imports.spec.js +23 -23
- package/dist/files/tests/imports.spec.js.map +1 -1
- package/dist/interfaces.d.ts +29 -8
- package/dist/lexer/Lexer.spec.js +8 -0
- package/dist/lexer/Lexer.spec.js.map +1 -1
- package/dist/lexer/TokenKind.d.ts +2 -0
- package/dist/lexer/TokenKind.js +5 -0
- package/dist/lexer/TokenKind.js.map +1 -1
- package/dist/parser/Parser.d.ts +10 -1
- package/dist/parser/Parser.js +90 -1
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/SGParser.spec.js +1 -1
- package/dist/parser/SGParser.spec.js.map +1 -1
- package/dist/parser/Statement.d.ts +52 -0
- package/dist/parser/Statement.js +154 -1
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/Statement.spec.js +1 -1
- package/dist/parser/Statement.spec.js.map +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +1 -1
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
- package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
- package/dist/parser/tests/statement/Enum.spec.js +774 -0
- package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
- package/dist/parser/tests/statement/InterfaceStatement.spec.js +1 -1
- package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
- package/dist/types/FunctionType.d.ts +2 -2
- package/dist/types/FunctionType.js +3 -3
- package/dist/types/FunctionType.js.map +1 -1
- package/dist/types/FunctionType.spec.js +2 -2
- package/dist/types/FunctionType.spec.js.map +1 -1
- package/dist/util.d.ts +22 -0
- package/dist/util.js +60 -0
- package/dist/util.js.map +1 -1
- package/package.json +2 -3
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.d.ts +0 -7
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js +0 -63
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js.map +0 -1
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +0 -1
package/dist/Program.d.ts
CHANGED
|
@@ -4,12 +4,13 @@ import type { BsConfig } from './BsConfig';
|
|
|
4
4
|
import { Scope } from './Scope';
|
|
5
5
|
import { BrsFile } from './files/BrsFile';
|
|
6
6
|
import { XmlFile } from './files/XmlFile';
|
|
7
|
-
import type { BsDiagnostic, File, FileReference, FileObj, BscFile, SemanticToken } from './interfaces';
|
|
7
|
+
import type { BsDiagnostic, File, FileReference, FileObj, BscFile, SemanticToken, FileLink } from './interfaces';
|
|
8
8
|
import { XmlScope } from './XmlScope';
|
|
9
9
|
import { Logger } from './Logger';
|
|
10
10
|
import type { ManifestValue } from './preprocessor/Manifest';
|
|
11
11
|
import PluginInterface from './PluginInterface';
|
|
12
12
|
import type { FunctionStatement, Statement } from './parser/Statement';
|
|
13
|
+
import type { SourceMapGenerator } from 'source-map';
|
|
13
14
|
export interface SourceObj {
|
|
14
15
|
pathAbsolute: string;
|
|
15
16
|
source: string;
|
|
@@ -24,10 +25,6 @@ export interface SignatureInfoObj {
|
|
|
24
25
|
key: string;
|
|
25
26
|
signature: SignatureInformation;
|
|
26
27
|
}
|
|
27
|
-
export interface FileLink<T> {
|
|
28
|
-
item: T;
|
|
29
|
-
file: BrsFile;
|
|
30
|
-
}
|
|
31
28
|
export declare class Program {
|
|
32
29
|
/**
|
|
33
30
|
* The root directory for this program
|
|
@@ -116,8 +113,9 @@ export declare class Program {
|
|
|
116
113
|
/**
|
|
117
114
|
* Determine if the specified file is loaded in this program right now.
|
|
118
115
|
* @param filePath
|
|
116
|
+
* @param normalizePath should the provided path be normalized before use
|
|
119
117
|
*/
|
|
120
|
-
hasFile(filePath: string): boolean;
|
|
118
|
+
hasFile(filePath: string, normalizePath?: boolean): boolean;
|
|
121
119
|
getPkgPath(...args: any[]): any;
|
|
122
120
|
/**
|
|
123
121
|
* roku filesystem is case INsensitive, so find the scope by key case insensitive
|
|
@@ -132,19 +130,42 @@ export declare class Program {
|
|
|
132
130
|
* Find the scope for the specified component
|
|
133
131
|
*/
|
|
134
132
|
getComponentScope(componentName: string): XmlScope;
|
|
133
|
+
/**
|
|
134
|
+
* Update internal maps with this file reference
|
|
135
|
+
*/
|
|
136
|
+
private assignFile;
|
|
137
|
+
/**
|
|
138
|
+
* Remove this file from internal maps
|
|
139
|
+
*/
|
|
140
|
+
private unassignFile;
|
|
135
141
|
/**
|
|
136
142
|
* Load a file into the program. If that file already exists, it is replaced.
|
|
137
143
|
* If file contents are provided, those are used, Otherwise, the file is loaded from the file system
|
|
138
|
-
* @param
|
|
144
|
+
* @param srcPath the file path relative to the root dir
|
|
139
145
|
* @param fileContents the file contents
|
|
146
|
+
* @deprecated use `setFile` instead
|
|
140
147
|
*/
|
|
141
|
-
addOrReplaceFile<T extends BscFile>(
|
|
148
|
+
addOrReplaceFile<T extends BscFile>(srcPath: string, fileContents: string): T;
|
|
142
149
|
/**
|
|
143
150
|
* Load a file into the program. If that file already exists, it is replaced.
|
|
144
151
|
* @param fileEntry an object that specifies src and dest for the file.
|
|
145
152
|
* @param fileContents the file contents. If not provided, the file will be loaded from disk
|
|
153
|
+
* @deprecated use `setFile` instead
|
|
146
154
|
*/
|
|
147
155
|
addOrReplaceFile<T extends BscFile>(fileEntry: FileObj, fileContents: string): T;
|
|
156
|
+
/**
|
|
157
|
+
* Load a file into the program. If that file already exists, it is replaced.
|
|
158
|
+
* If file contents are provided, those are used, Otherwise, the file is loaded from the file system
|
|
159
|
+
* @param srcDestOrPkgPath the absolute path, the pkg path (i.e. `pkg:/path/to/file.brs`), or the destPath (i.e. `path/to/file.brs` relative to `pkg:/`)
|
|
160
|
+
* @param fileContents the file contents
|
|
161
|
+
*/
|
|
162
|
+
setFile<T extends BscFile>(srcDestOrPkgPath: string, fileContents: string): T;
|
|
163
|
+
/**
|
|
164
|
+
* Load a file into the program. If that file already exists, it is replaced.
|
|
165
|
+
* @param fileEntry an object that specifies src and dest for the file.
|
|
166
|
+
* @param fileContents the file contents. If not provided, the file will be loaded from disk
|
|
167
|
+
*/
|
|
168
|
+
setFile<T extends BscFile>(fileEntry: FileObj, fileContents: string): T;
|
|
148
169
|
/**
|
|
149
170
|
* Ensure source scope is created.
|
|
150
171
|
* Note: automatically called internally, and no-op if it exists already.
|
|
@@ -155,28 +176,33 @@ export declare class Program {
|
|
|
155
176
|
* Roku is a case insensitive file system. It is an error to have multiple files
|
|
156
177
|
* with the same path with only case being different.
|
|
157
178
|
* @param pathAbsolute
|
|
179
|
+
* @deprecated use `getFile` instead, which auto-detects the path type
|
|
158
180
|
*/
|
|
159
181
|
getFileByPathAbsolute<T extends BrsFile | XmlFile>(pathAbsolute: string): T;
|
|
160
182
|
/**
|
|
161
183
|
* Get a list of files for the given (platform-normalized) pkgPath array.
|
|
162
184
|
* Missing files are just ignored.
|
|
185
|
+
* @deprecated use `getFiles` instead, which auto-detects the path types
|
|
163
186
|
*/
|
|
164
187
|
getFilesByPkgPaths<T extends BscFile[]>(pkgPaths: string[]): T;
|
|
165
188
|
/**
|
|
166
189
|
* Get a file with the specified (platform-normalized) pkg path.
|
|
167
190
|
* If not found, return undefined
|
|
191
|
+
* @deprecated use `getFile` instead, which auto-detects the path type
|
|
168
192
|
*/
|
|
169
193
|
getFileByPkgPath<T extends BscFile>(pkgPath: string): T;
|
|
170
194
|
/**
|
|
171
195
|
* Remove a set of files from the program
|
|
172
|
-
* @param
|
|
196
|
+
* @param filePaths can be an array of srcPath or destPath strings
|
|
197
|
+
* @param normalizePath should this function repair and standardize the filePaths? Passing false should have a performance boost if you can guarantee your paths are already sanitized
|
|
173
198
|
*/
|
|
174
|
-
removeFiles(
|
|
199
|
+
removeFiles(srcPaths: string[], normalizePath?: boolean): void;
|
|
175
200
|
/**
|
|
176
201
|
* Remove a file from the program
|
|
177
|
-
* @param
|
|
202
|
+
* @param filePath can be a srcPath, a pkgPath, or a destPath (same as pkgPath but without `pkg:/`)
|
|
203
|
+
* @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
|
|
178
204
|
*/
|
|
179
|
-
removeFile(
|
|
205
|
+
removeFile(filePath: string, normalizePath?: boolean): void;
|
|
180
206
|
/**
|
|
181
207
|
* Traverse the entire project, and validate all scopes
|
|
182
208
|
* @param force - if true, then all scopes are force to validate, even if they aren't marked as dirty
|
|
@@ -190,25 +216,35 @@ export declare class Program {
|
|
|
190
216
|
* Determine if the given file is included in at least one scope in this program
|
|
191
217
|
*/
|
|
192
218
|
private fileIsIncludedInAnyScope;
|
|
219
|
+
/**
|
|
220
|
+
* Get the files for a list of filePaths
|
|
221
|
+
* @param filePaths can be an array of srcPath or a destPath strings
|
|
222
|
+
* @param normalizePath should this function repair and standardize the paths? Passing false should have a performance boost if you can guarantee your paths are already sanitized
|
|
223
|
+
*/
|
|
224
|
+
getFiles<T extends BscFile>(filePaths: string[], normalizePath?: boolean): T[];
|
|
193
225
|
/**
|
|
194
226
|
* Get the file at the given path
|
|
195
|
-
* @param
|
|
227
|
+
* @param filePath can be a srcPath or a destPath
|
|
228
|
+
* @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
|
|
196
229
|
*/
|
|
197
|
-
|
|
230
|
+
getFile<T extends BscFile>(filePath: string, normalizePath?: boolean): T;
|
|
198
231
|
/**
|
|
199
232
|
* Get a list of all scopes the file is loaded into
|
|
200
233
|
* @param file
|
|
201
234
|
*/
|
|
202
235
|
getScopesForFile(file: XmlFile | BrsFile): Scope[];
|
|
236
|
+
/**
|
|
237
|
+
* Get the first found scope for a file.
|
|
238
|
+
*/
|
|
239
|
+
getFirstScopeForFile(file: XmlFile | BrsFile): Scope;
|
|
203
240
|
getStatementsByName(name: string, originFile: BrsFile, namespaceName?: string): FileLink<Statement>[];
|
|
204
241
|
getStatementsForXmlFile(scope: XmlScope, filterName?: string): FileLink<FunctionStatement>[];
|
|
205
242
|
/**
|
|
206
243
|
* Find all available completion items at the given position
|
|
207
|
-
* @param
|
|
208
|
-
* @param
|
|
209
|
-
* @param columnIndex
|
|
244
|
+
* @param filePath can be a srcPath or a destPath
|
|
245
|
+
* @param position the position (line & column) where completions should be found
|
|
210
246
|
*/
|
|
211
|
-
getCompletions(
|
|
247
|
+
getCompletions(filePath: string, position: Position): CompletionItem[];
|
|
212
248
|
/**
|
|
213
249
|
* Goes through each file and builds a list of workspace symbols for the program. Used by LanguageServer's onWorkspaceSymbol functionality
|
|
214
250
|
*/
|
|
@@ -240,12 +276,12 @@ export declare class Program {
|
|
|
240
276
|
* Transpile a single file and get the result as a string.
|
|
241
277
|
* This does not write anything to the file system.
|
|
242
278
|
*/
|
|
243
|
-
getTranspiledFileContents(pathAbsolute: string):
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
279
|
+
getTranspiledFileContents(pathAbsolute: string): FileTranspileResult;
|
|
280
|
+
/**
|
|
281
|
+
* Internal function used to transpile files.
|
|
282
|
+
* This does not write anything to the file system
|
|
283
|
+
*/
|
|
284
|
+
private _getTranspiledFileContents;
|
|
249
285
|
transpile(fileEntries: FileObj[], stagingFolderPath: string): Promise<void>;
|
|
250
286
|
/**
|
|
251
287
|
* Find a list of files in the program that have a function with the given name (case INsensitive)
|
|
@@ -262,3 +298,10 @@ export declare class Program {
|
|
|
262
298
|
private _manifest;
|
|
263
299
|
dispose(): void;
|
|
264
300
|
}
|
|
301
|
+
export interface FileTranspileResult {
|
|
302
|
+
pathAbsolute: string;
|
|
303
|
+
pkgPath: string;
|
|
304
|
+
code: string;
|
|
305
|
+
map: SourceMapGenerator;
|
|
306
|
+
typedef: string;
|
|
307
|
+
}
|
package/dist/Program.js
CHANGED
|
@@ -87,11 +87,11 @@ class Program {
|
|
|
87
87
|
*/
|
|
88
88
|
get bslibPkgPath() {
|
|
89
89
|
//if there's an aliased (preferred) version of bslib from roku_modules loaded into the program, use that
|
|
90
|
-
if (this.
|
|
90
|
+
if (this.getFile(bslibAliasedRokuModulesPkgPath)) {
|
|
91
91
|
return bslibAliasedRokuModulesPkgPath;
|
|
92
92
|
//if there's a non-aliased version of bslib from roku_modules, use that
|
|
93
93
|
}
|
|
94
|
-
else if (this.
|
|
94
|
+
else if (this.getFile(bslibNonAliasedRokuModulesPkgPath)) {
|
|
95
95
|
return bslibNonAliasedRokuModulesPkgPath;
|
|
96
96
|
//default to the embedded version
|
|
97
97
|
}
|
|
@@ -220,10 +220,10 @@ class Program {
|
|
|
220
220
|
/**
|
|
221
221
|
* Determine if the specified file is loaded in this program right now.
|
|
222
222
|
* @param filePath
|
|
223
|
+
* @param normalizePath should the provided path be normalized before use
|
|
223
224
|
*/
|
|
224
|
-
hasFile(filePath) {
|
|
225
|
-
|
|
226
|
-
return this.files[filePath] !== undefined;
|
|
225
|
+
hasFile(filePath, normalizePath = true) {
|
|
226
|
+
return !!this.getFile(filePath, normalizePath);
|
|
227
227
|
}
|
|
228
228
|
getPkgPath(...args) {
|
|
229
229
|
throw new Error('Not implemented');
|
|
@@ -255,8 +255,27 @@ class Program {
|
|
|
255
255
|
var _a;
|
|
256
256
|
return (_a = this.getComponent(componentName)) === null || _a === void 0 ? void 0 : _a.scope;
|
|
257
257
|
}
|
|
258
|
+
/**
|
|
259
|
+
* Update internal maps with this file reference
|
|
260
|
+
*/
|
|
261
|
+
assignFile(file) {
|
|
262
|
+
this.files[file.pathAbsolute.toLowerCase()] = file;
|
|
263
|
+
this.pkgMap[file.pkgPath.toLowerCase()] = file;
|
|
264
|
+
return file;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Remove this file from internal maps
|
|
268
|
+
*/
|
|
269
|
+
unassignFile(file) {
|
|
270
|
+
delete this.files[file.pathAbsolute.toLowerCase()];
|
|
271
|
+
delete this.pkgMap[file.pkgPath.toLowerCase()];
|
|
272
|
+
return file;
|
|
273
|
+
}
|
|
258
274
|
addOrReplaceFile(fileParam, fileContents) {
|
|
259
|
-
|
|
275
|
+
return this.setFile(fileParam, fileContents);
|
|
276
|
+
}
|
|
277
|
+
setFile(fileParam, fileContents) {
|
|
278
|
+
assert.ok(fileParam, 'fileParam is required');
|
|
260
279
|
let srcPath;
|
|
261
280
|
let pkgPath;
|
|
262
281
|
if (typeof fileParam === 'string') {
|
|
@@ -267,7 +286,7 @@ class Program {
|
|
|
267
286
|
srcPath = (0, util_1.standardizePath) `${fileParam.src}`;
|
|
268
287
|
pkgPath = (0, util_1.standardizePath) `${fileParam.dest}`;
|
|
269
288
|
}
|
|
270
|
-
let file = this.logger.time(Logger_1.LogLevel.debug, ['Program.
|
|
289
|
+
let file = this.logger.time(Logger_1.LogLevel.debug, ['Program.setFile()', chalk_1.default.green(srcPath)], () => {
|
|
271
290
|
assert.ok(srcPath, 'fileEntry.src is required');
|
|
272
291
|
assert.ok(pkgPath, 'fileEntry.dest is required');
|
|
273
292
|
//if the file is already loaded, remove it
|
|
@@ -277,15 +296,13 @@ class Program {
|
|
|
277
296
|
let fileExtension = path.extname(srcPath).toLowerCase();
|
|
278
297
|
let file;
|
|
279
298
|
if (fileExtension === '.brs' || fileExtension === '.bs') {
|
|
280
|
-
|
|
299
|
+
//add the file to the program
|
|
300
|
+
const brsFile = this.assignFile(new BrsFile_1.BrsFile(srcPath, pkgPath, this));
|
|
281
301
|
//add file to the `source` dependency list
|
|
282
302
|
if (brsFile.pkgPath.startsWith(startOfSourcePkgPath)) {
|
|
283
303
|
this.createSourceScope();
|
|
284
304
|
this.dependencyGraph.addDependency('scope:source', brsFile.dependencyGraphKey);
|
|
285
305
|
}
|
|
286
|
-
//add the file to the program
|
|
287
|
-
this.files[srcPath] = brsFile;
|
|
288
|
-
this.pkgMap[brsFile.pkgPath.toLowerCase()] = brsFile;
|
|
289
306
|
let sourceObj = {
|
|
290
307
|
pathAbsolute: srcPath,
|
|
291
308
|
source: fileContents
|
|
@@ -298,27 +315,14 @@ class Program {
|
|
|
298
315
|
this.plugins.emit('afterFileParse', brsFile);
|
|
299
316
|
file = brsFile;
|
|
300
317
|
brsFile.attachDependencyGraph(this.dependencyGraph);
|
|
301
|
-
this.plugins.emit('beforeFileValidate', {
|
|
302
|
-
program: this,
|
|
303
|
-
file: file
|
|
304
|
-
});
|
|
305
|
-
file.validate();
|
|
306
|
-
//emit an event to allow plugins to contribute to the file validation process
|
|
307
|
-
this.plugins.emit('onFileValidate', {
|
|
308
|
-
program: this,
|
|
309
|
-
file: file
|
|
310
|
-
});
|
|
311
|
-
this.plugins.emit('afterFileValidate', brsFile);
|
|
312
318
|
}
|
|
313
319
|
else if (
|
|
314
320
|
//is xml file
|
|
315
321
|
fileExtension === '.xml' &&
|
|
316
322
|
//resides in the components folder (Roku will only parse xml files in the components folder)
|
|
317
323
|
pkgPath.toLowerCase().startsWith(util_1.util.pathSepNormalize(`components/`))) {
|
|
318
|
-
let xmlFile = new XmlFile_1.XmlFile(srcPath, pkgPath, this);
|
|
319
324
|
//add the file to the program
|
|
320
|
-
this.
|
|
321
|
-
this.pkgMap[xmlFile.pkgPath.toLowerCase()] = xmlFile;
|
|
325
|
+
const xmlFile = this.assignFile(new XmlFile_1.XmlFile(srcPath, pkgPath, this));
|
|
322
326
|
let sourceObj = {
|
|
323
327
|
pathAbsolute: srcPath,
|
|
324
328
|
source: fileContents
|
|
@@ -335,18 +339,6 @@ class Program {
|
|
|
335
339
|
this.addScope(scope);
|
|
336
340
|
//register this compoent now that we have parsed it and know its component name
|
|
337
341
|
this.registerComponent(xmlFile, scope);
|
|
338
|
-
//emit an event before starting to validate this file
|
|
339
|
-
this.plugins.emit('beforeFileValidate', {
|
|
340
|
-
file: file,
|
|
341
|
-
program: this
|
|
342
|
-
});
|
|
343
|
-
xmlFile.validate();
|
|
344
|
-
//emit an event to allow plugins to contribute to the file validation process
|
|
345
|
-
this.plugins.emit('onFileValidate', {
|
|
346
|
-
file: xmlFile,
|
|
347
|
-
program: this
|
|
348
|
-
});
|
|
349
|
-
this.plugins.emit('afterFileValidate', xmlFile);
|
|
350
342
|
}
|
|
351
343
|
else {
|
|
352
344
|
//TODO do we actually need to implement this? Figure out how to handle img paths
|
|
@@ -377,6 +369,7 @@ class Program {
|
|
|
377
369
|
* Roku is a case insensitive file system. It is an error to have multiple files
|
|
378
370
|
* with the same path with only case being different.
|
|
379
371
|
* @param pathAbsolute
|
|
372
|
+
* @deprecated use `getFile` instead, which auto-detects the path type
|
|
380
373
|
*/
|
|
381
374
|
getFileByPathAbsolute(pathAbsolute) {
|
|
382
375
|
pathAbsolute = (0, util_1.standardizePath) `${pathAbsolute}`;
|
|
@@ -389,6 +382,7 @@ class Program {
|
|
|
389
382
|
/**
|
|
390
383
|
* Get a list of files for the given (platform-normalized) pkgPath array.
|
|
391
384
|
* Missing files are just ignored.
|
|
385
|
+
* @deprecated use `getFiles` instead, which auto-detects the path types
|
|
392
386
|
*/
|
|
393
387
|
getFilesByPkgPaths(pkgPaths) {
|
|
394
388
|
return pkgPaths
|
|
@@ -398,29 +392,29 @@ class Program {
|
|
|
398
392
|
/**
|
|
399
393
|
* Get a file with the specified (platform-normalized) pkg path.
|
|
400
394
|
* If not found, return undefined
|
|
395
|
+
* @deprecated use `getFile` instead, which auto-detects the path type
|
|
401
396
|
*/
|
|
402
397
|
getFileByPkgPath(pkgPath) {
|
|
403
398
|
return this.pkgMap[pkgPath.toLowerCase()];
|
|
404
399
|
}
|
|
405
400
|
/**
|
|
406
401
|
* Remove a set of files from the program
|
|
407
|
-
* @param
|
|
402
|
+
* @param filePaths can be an array of srcPath or destPath strings
|
|
403
|
+
* @param normalizePath should this function repair and standardize the filePaths? Passing false should have a performance boost if you can guarantee your paths are already sanitized
|
|
408
404
|
*/
|
|
409
|
-
removeFiles(
|
|
410
|
-
for (let
|
|
411
|
-
this.removeFile(
|
|
405
|
+
removeFiles(srcPaths, normalizePath = true) {
|
|
406
|
+
for (let srcPath of srcPaths) {
|
|
407
|
+
this.removeFile(srcPath, normalizePath);
|
|
412
408
|
}
|
|
413
409
|
}
|
|
414
410
|
/**
|
|
415
411
|
* Remove a file from the program
|
|
416
|
-
* @param
|
|
412
|
+
* @param filePath can be a srcPath, a pkgPath, or a destPath (same as pkgPath but without `pkg:/`)
|
|
413
|
+
* @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
|
|
417
414
|
*/
|
|
418
|
-
removeFile(
|
|
419
|
-
this.logger.debug('Program.removeFile()',
|
|
420
|
-
|
|
421
|
-
throw new Error(`Path must be absolute: "${pathAbsolute}"`);
|
|
422
|
-
}
|
|
423
|
-
let file = this.getFile(pathAbsolute);
|
|
415
|
+
removeFile(filePath, normalizePath = true) {
|
|
416
|
+
this.logger.debug('Program.removeFile()', filePath);
|
|
417
|
+
let file = this.getFile(filePath, normalizePath);
|
|
424
418
|
if (file) {
|
|
425
419
|
this.plugins.emit('beforeFileDispose', file);
|
|
426
420
|
//if there is a scope named the same as this file's path, remove it (i.e. xml scopes)
|
|
@@ -434,8 +428,7 @@ class Program {
|
|
|
434
428
|
this.plugins.emit('afterScopeDispose', scope);
|
|
435
429
|
}
|
|
436
430
|
//remove the file from the program
|
|
437
|
-
|
|
438
|
-
delete this.pkgMap[file.pkgPath.toLowerCase()];
|
|
431
|
+
this.unassignFile(file);
|
|
439
432
|
this.dependencyGraph.remove(file.dependencyGraphKey);
|
|
440
433
|
//if this is a pkg:/source file, notify the `source` scope that it has changed
|
|
441
434
|
if (file.pkgPath.startsWith(startOfSourcePkgPath)) {
|
|
@@ -454,23 +447,40 @@ class Program {
|
|
|
454
447
|
*/
|
|
455
448
|
validate() {
|
|
456
449
|
this.logger.time(Logger_1.LogLevel.log, ['Validating project'], () => {
|
|
450
|
+
var _a;
|
|
457
451
|
this.diagnostics = [];
|
|
458
452
|
this.plugins.emit('beforeProgramValidate', this);
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
scope.validate();
|
|
463
|
-
}
|
|
464
|
-
});
|
|
465
|
-
//find any files NOT loaded into a scope
|
|
466
|
-
for (let filePath in this.files) {
|
|
467
|
-
let file = this.files[filePath];
|
|
453
|
+
//validate every file
|
|
454
|
+
for (const file of Object.values(this.files)) {
|
|
455
|
+
//find any files NOT loaded into a scope
|
|
468
456
|
if (!this.fileIsIncludedInAnyScope(file)) {
|
|
469
457
|
this.logger.debug('Program.validate(): fileNotReferenced by any scope', () => chalk_1.default.green(file === null || file === void 0 ? void 0 : file.pkgPath));
|
|
470
458
|
//the file is not loaded in any scope
|
|
471
459
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.fileNotReferencedByAnyOtherFile()), { file: file, range: util_1.util.createRange(0, 0, 0, Number.MAX_VALUE) }));
|
|
472
460
|
}
|
|
461
|
+
//for every unvalidated file, validate it
|
|
462
|
+
if (!file.isValidated) {
|
|
463
|
+
this.plugins.emit('beforeFileValidate', {
|
|
464
|
+
program: this,
|
|
465
|
+
file: file
|
|
466
|
+
});
|
|
467
|
+
//emit an event to allow plugins to contribute to the file validation process
|
|
468
|
+
this.plugins.emit('onFileValidate', {
|
|
469
|
+
program: this,
|
|
470
|
+
file: file
|
|
471
|
+
});
|
|
472
|
+
//call file.validate() IF the file has that function defined
|
|
473
|
+
(_a = file.validate) === null || _a === void 0 ? void 0 : _a.call(file);
|
|
474
|
+
file.isValidated = true;
|
|
475
|
+
this.plugins.emit('afterFileValidate', file);
|
|
476
|
+
}
|
|
473
477
|
}
|
|
478
|
+
this.logger.time(Logger_1.LogLevel.info, ['Validate all scopes'], () => {
|
|
479
|
+
for (let scopeName in this.scopes) {
|
|
480
|
+
let scope = this.scopes[scopeName];
|
|
481
|
+
scope.validate();
|
|
482
|
+
}
|
|
483
|
+
});
|
|
474
484
|
this.detectDuplicateComponentNames();
|
|
475
485
|
this.plugins.emit('afterProgramValidate', this);
|
|
476
486
|
});
|
|
@@ -519,13 +529,31 @@ class Program {
|
|
|
519
529
|
}
|
|
520
530
|
return false;
|
|
521
531
|
}
|
|
532
|
+
/**
|
|
533
|
+
* Get the files for a list of filePaths
|
|
534
|
+
* @param filePaths can be an array of srcPath or a destPath strings
|
|
535
|
+
* @param normalizePath should this function repair and standardize the paths? Passing false should have a performance boost if you can guarantee your paths are already sanitized
|
|
536
|
+
*/
|
|
537
|
+
getFiles(filePaths, normalizePath = true) {
|
|
538
|
+
return filePaths
|
|
539
|
+
.map(filePath => this.getFile(filePath, normalizePath))
|
|
540
|
+
.filter(file => file !== undefined);
|
|
541
|
+
}
|
|
522
542
|
/**
|
|
523
543
|
* Get the file at the given path
|
|
524
|
-
* @param
|
|
544
|
+
* @param filePath can be a srcPath or a destPath
|
|
545
|
+
* @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
|
|
525
546
|
*/
|
|
526
|
-
getFile(
|
|
527
|
-
|
|
528
|
-
|
|
547
|
+
getFile(filePath, normalizePath = true) {
|
|
548
|
+
if (typeof filePath !== 'string') {
|
|
549
|
+
return undefined;
|
|
550
|
+
}
|
|
551
|
+
else if (path.isAbsolute(filePath)) {
|
|
552
|
+
return this.files[(normalizePath ? util_1.util.standardizePath(filePath) : filePath).toLowerCase()];
|
|
553
|
+
}
|
|
554
|
+
else {
|
|
555
|
+
return this.pkgMap[(normalizePath ? util_1.util.standardizePath(filePath) : filePath).toLowerCase()];
|
|
556
|
+
}
|
|
529
557
|
}
|
|
530
558
|
/**
|
|
531
559
|
* Get a list of all scopes the file is loaded into
|
|
@@ -541,6 +569,17 @@ class Program {
|
|
|
541
569
|
}
|
|
542
570
|
return result;
|
|
543
571
|
}
|
|
572
|
+
/**
|
|
573
|
+
* Get the first found scope for a file.
|
|
574
|
+
*/
|
|
575
|
+
getFirstScopeForFile(file) {
|
|
576
|
+
for (let key in this.scopes) {
|
|
577
|
+
let scope = this.scopes[key];
|
|
578
|
+
if (scope.hasFile(file)) {
|
|
579
|
+
return scope;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
544
583
|
getStatementsByName(name, originFile, namespaceName) {
|
|
545
584
|
var _a, _b;
|
|
546
585
|
let results = new Map();
|
|
@@ -599,12 +638,11 @@ class Program {
|
|
|
599
638
|
}
|
|
600
639
|
/**
|
|
601
640
|
* Find all available completion items at the given position
|
|
602
|
-
* @param
|
|
603
|
-
* @param
|
|
604
|
-
* @param columnIndex
|
|
641
|
+
* @param filePath can be a srcPath or a destPath
|
|
642
|
+
* @param position the position (line & column) where completions should be found
|
|
605
643
|
*/
|
|
606
|
-
getCompletions(
|
|
607
|
-
let file = this.getFile(
|
|
644
|
+
getCompletions(filePath, position) {
|
|
645
|
+
let file = this.getFile(filePath);
|
|
608
646
|
if (!file) {
|
|
609
647
|
return [];
|
|
610
648
|
}
|
|
@@ -996,9 +1034,49 @@ class Program {
|
|
|
996
1034
|
* This does not write anything to the file system.
|
|
997
1035
|
*/
|
|
998
1036
|
getTranspiledFileContents(pathAbsolute) {
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1037
|
+
return this._getTranspiledFileContents(this.getFile(pathAbsolute));
|
|
1038
|
+
}
|
|
1039
|
+
/**
|
|
1040
|
+
* Internal function used to transpile files.
|
|
1041
|
+
* This does not write anything to the file system
|
|
1042
|
+
*/
|
|
1043
|
+
_getTranspiledFileContents(file, outputPath) {
|
|
1044
|
+
const editor = new AstEditor_1.AstEditor();
|
|
1045
|
+
this.plugins.emit('beforeFileTranspile', {
|
|
1046
|
+
file: file,
|
|
1047
|
+
outputPath: outputPath,
|
|
1048
|
+
editor: editor
|
|
1049
|
+
});
|
|
1050
|
+
//if we have any edits, assume the file needs to be transpiled
|
|
1051
|
+
if (editor.hasChanges) {
|
|
1052
|
+
//use the `editor` because it'll track the previous value for us and revert later on
|
|
1053
|
+
editor.setProperty(file, 'needsTranspiled', true);
|
|
1054
|
+
}
|
|
1055
|
+
//transpile the file
|
|
1056
|
+
const result = file.transpile();
|
|
1057
|
+
//generate the typedef if enabled
|
|
1058
|
+
let typedef;
|
|
1059
|
+
if ((0, reflection_1.isBrsFile)(file) && this.options.emitDefinitions) {
|
|
1060
|
+
typedef = file.getTypedef();
|
|
1061
|
+
}
|
|
1062
|
+
const event = {
|
|
1063
|
+
file: file,
|
|
1064
|
+
outputPath: outputPath,
|
|
1065
|
+
editor: editor,
|
|
1066
|
+
code: result.code,
|
|
1067
|
+
map: result.map,
|
|
1068
|
+
typedef: typedef
|
|
1069
|
+
};
|
|
1070
|
+
this.plugins.emit('afterFileTranspile', event);
|
|
1071
|
+
//undo all `editor` edits that may have been applied to this file.
|
|
1072
|
+
editor.undoAll();
|
|
1073
|
+
return {
|
|
1074
|
+
pathAbsolute: file.pathAbsolute,
|
|
1075
|
+
pkgPath: file.pkgPath,
|
|
1076
|
+
code: event.code,
|
|
1077
|
+
map: event.map,
|
|
1078
|
+
typedef: event.typedef
|
|
1079
|
+
};
|
|
1002
1080
|
}
|
|
1003
1081
|
async transpile(fileEntries, stagingFolderPath) {
|
|
1004
1082
|
// map fileEntries using their path as key, to avoid excessive "find()" operations
|
|
@@ -1022,8 +1100,7 @@ class Program {
|
|
|
1022
1100
|
outputPath = (0, util_1.standardizePath) `${stagingFolderPath}/${outputPath}`;
|
|
1023
1101
|
return {
|
|
1024
1102
|
file: file,
|
|
1025
|
-
outputPath: outputPath
|
|
1026
|
-
editor: new AstEditor_1.AstEditor()
|
|
1103
|
+
outputPath: outputPath
|
|
1027
1104
|
};
|
|
1028
1105
|
});
|
|
1029
1106
|
this.plugins.emit('beforeProgramTranspile', this, entries);
|
|
@@ -1032,32 +1109,22 @@ class Program {
|
|
|
1032
1109
|
if ((0, reflection_1.isBrsFile)(entry.file) && entry.file.isTypedef) {
|
|
1033
1110
|
return;
|
|
1034
1111
|
}
|
|
1035
|
-
this.plugins.emit('beforeFileTranspile', entry);
|
|
1036
1112
|
const { file, outputPath } = entry;
|
|
1037
|
-
|
|
1038
|
-
if (entry.editor.hasChanges) {
|
|
1039
|
-
//use the `editor` because it'll track the previous value for us and revert later on
|
|
1040
|
-
entry.editor.setProperty(file, 'needsTranspiled', true);
|
|
1041
|
-
}
|
|
1042
|
-
const result = file.transpile();
|
|
1113
|
+
const fileTranspileResult = this._getTranspiledFileContents(file, outputPath);
|
|
1043
1114
|
//make sure the full dir path exists
|
|
1044
1115
|
await fsExtra.ensureDir(path.dirname(outputPath));
|
|
1045
1116
|
if (await fsExtra.pathExists(outputPath)) {
|
|
1046
1117
|
throw new Error(`Error while transpiling "${file.pathAbsolute}". A file already exists at "${outputPath}" and will not be overwritten.`);
|
|
1047
1118
|
}
|
|
1048
|
-
const writeMapPromise =
|
|
1119
|
+
const writeMapPromise = fileTranspileResult.map ? fsExtra.writeFile(`${outputPath}.map`, fileTranspileResult.map.toString()) : null;
|
|
1049
1120
|
await Promise.all([
|
|
1050
|
-
fsExtra.writeFile(outputPath,
|
|
1121
|
+
fsExtra.writeFile(outputPath, fileTranspileResult.code),
|
|
1051
1122
|
writeMapPromise
|
|
1052
1123
|
]);
|
|
1053
|
-
if (
|
|
1054
|
-
const typedef = file.getTypedef();
|
|
1124
|
+
if (fileTranspileResult.typedef) {
|
|
1055
1125
|
const typedefPath = outputPath.replace(/\.brs$/i, '.d.bs');
|
|
1056
|
-
await fsExtra.writeFile(typedefPath, typedef);
|
|
1126
|
+
await fsExtra.writeFile(typedefPath, fileTranspileResult.typedef);
|
|
1057
1127
|
}
|
|
1058
|
-
this.plugins.emit('afterFileTranspile', entry);
|
|
1059
|
-
//undo all `editor` edits that may have been applied to this file.
|
|
1060
|
-
entry.editor.undoAll();
|
|
1061
1128
|
});
|
|
1062
1129
|
//if there's no bslib file already loaded into the program, copy it to the staging directory
|
|
1063
1130
|
if (!this.getFileByPkgPath(bslibAliasedRokuModulesPkgPath) && !this.getFileByPkgPath((0, util_1.standardizePath) `source/bslib.brs`)) {
|