From 0a751a80eec60c55c3c5230018e268f2a7e208ce Mon Sep 17 00:00:00 2001 From: George Cook Date: Sat, 26 Feb 2022 14:23:49 +0100 Subject: [PATCH] updates to bsc 0.45.2 --- .eslintrc.js | 1 + .vscode/launch.json | 2 +- package-lock.json | 73 +++--- package.json | 5 +- scripts/run.js | 109 ++++++++- src/lib/Utils.ts | 88 +++---- src/lib/binding/BindingProcessor.ts | 7 +- src/lib/files/File.ts | 1 + src/lib/importSupport/ImportProcessor.spec.ts | 4 +- src/lib/importSupport/ImportProcessor.ts | 5 + src/lib/node-classes/NodeClass.ts | 2 +- src/lib/reflection/ReflectionUtil.ts | 4 +- src/lib/utils/Utils.ts | 54 ++--- src/plugin.spec.ts | 219 ++++++++++++------ src/plugin.ts | 37 +-- 15 files changed, 408 insertions(+), 203 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 7b2ff56..dfd018c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -50,6 +50,7 @@ module.exports = { '@typescript-eslint/no-type-alias': 'off', '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'off', '@typescript-eslint/no-unnecessary-condition': 'off', + '@typescript-eslint/no-unsafe-argument': 'off', '@typescript-eslint/no-unsafe-assignment': 'off', '@typescript-eslint/no-unsafe-call': 'off', '@typescript-eslint/no-unsafe-member-access': 'off', diff --git a/.vscode/launch.json b/.vscode/launch.json index dace625..7196caf 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -14,7 +14,7 @@ "0" ], "skipFiles": [ - "${workspaceFolder}/node_modules/**/*.js", + // "${workspaceFolder}/node_modules/**/*.js", "/**/*.js" ], "cwd": "${workspaceRoot}", diff --git a/package-lock.json b/package-lock.json index d62b4d6..e007ae7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { "name": "maestro-roku-bsc-plugin", - "version": "0.15.3", + "version": "0.17.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "0.15.3", + "version": "0.17.0", "license": "ISC", "dependencies": { "debounce": "^1.2.0", @@ -21,7 +21,7 @@ "@typescript-eslint/eslint-plugin": "^4.4.1", "@typescript-eslint/parser": "^4.4.1", "auto-changelog": "^2.2.1", - "brighterscript": "^0.41.6", + "brighterscript": "0.45.3", "chai": "^4.2.0", "eslint": "^7.11.0", "eslint-plugin-github": "^4.1.1", @@ -35,6 +35,9 @@ "source-map-support": "^0.5.21", "ts-node": "^10.4.0", "typescript": "^4.1.3" + }, + "peerDependencies": { + "brighterscript": "^0.45.3" } }, "node_modules/@babel/code-frame": { @@ -766,9 +769,9 @@ "dev": true }, "node_modules/@xml-tools/parser": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@xml-tools/parser/-/parser-1.0.10.tgz", - "integrity": "sha512-9oRb68wEKT+MRB7e2GwTiKicRKVXKzquBDGgH6YcGafvnSYXorWi2oaTVtbv2109RlGiQSnoXaQFUXCnHwFS7Q==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@xml-tools/parser/-/parser-1.0.11.tgz", + "integrity": "sha512-aKqQ077XnR+oQtHJlrAflaZaL7qZsulWc/i/ZEooar5JiWj1eLt0+Wg28cpa+XLney107wXqneC+oG1IZvxkTA==", "dev": true, "dependencies": { "chevrotain": "7.1.1" @@ -1104,9 +1107,9 @@ } }, "node_modules/brighterscript": { - "version": "0.41.6", - "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.41.6.tgz", - "integrity": "sha512-HJ1fJaGlsmJGkpC4ObidtpFbdzS3umHPuuSZP46WOxgvVMNyos8QwTr6jhETxTu/eyMC7witqidpoeDta/XiIw==", + "version": "0.45.3", + "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.45.3.tgz", + "integrity": "sha512-FUjqrNsY7mfy9jAmYb23bVrgOjAeDdnKHRyT2KA8XYDOEegGPvVUgYtInYNGGzcWfiHXShO426aWB1lMcdg5cA==", "dev": true, "dependencies": { "@rokucommunity/bslib": "^0.1.1", @@ -1129,7 +1132,7 @@ "moment": "^2.23.0", "p-settle": "^2.1.0", "parse-ms": "^2.1.0", - "roku-deploy": "^3.5.0", + "roku-deploy": "^3.5.3", "serialize-error": "^7.0.1", "source-map": "^0.7.3", "vscode-languageserver": "7.0.0", @@ -3594,9 +3597,9 @@ } }, "node_modules/luxon": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.26.0.tgz", - "integrity": "sha512-+V5QIQ5f6CDXQpWNICELwjwuHdqeJM1UenlZWx5ujcRMc9venvluCjFb4t5NYLhb6IhkbMVOxzVuOqkgMxee2A==", + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.0.tgz", + "integrity": "sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ==", "dev": true, "engines": { "node": "*" @@ -4881,9 +4884,9 @@ } }, "node_modules/roku-deploy": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.5.2.tgz", - "integrity": "sha512-W5Dfc/V7m0MdvQoYOA2PzxC5EGfyZTIjqWomGGKfkPPEwO1L5n7OP4o8Yga42z4c0u0K68yuuSQu20xwgj5d9g==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.5.3.tgz", + "integrity": "sha512-a9J6aI2ASCYkDS7FrKSRre532nIXTdhJIOAxHqlWUC692OHlUpMDmQXBPujWX7geNQSG9Y/uJkHNbE+dJVAqgw==", "dependencies": { "chalk": "^2.4.2", "dateformat": "^3.0.3", @@ -5737,9 +5740,9 @@ } }, "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz", - "integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.4.tgz", + "integrity": "sha512-/xhqXP/2A2RSs+J8JNXpiiNVvvNM0oTosNVmQnunlKvq9o4mupHOBAnnzH0lwIPKazXKvAKsVp1kr+H/K4lgoQ==", "dev": true }, "node_modules/vscode-languageserver-types": { @@ -6641,9 +6644,9 @@ "dev": true }, "@xml-tools/parser": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@xml-tools/parser/-/parser-1.0.10.tgz", - "integrity": "sha512-9oRb68wEKT+MRB7e2GwTiKicRKVXKzquBDGgH6YcGafvnSYXorWi2oaTVtbv2109RlGiQSnoXaQFUXCnHwFS7Q==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@xml-tools/parser/-/parser-1.0.11.tgz", + "integrity": "sha512-aKqQ077XnR+oQtHJlrAflaZaL7qZsulWc/i/ZEooar5JiWj1eLt0+Wg28cpa+XLney107wXqneC+oG1IZvxkTA==", "dev": true, "requires": { "chevrotain": "7.1.1" @@ -6902,9 +6905,9 @@ } }, "brighterscript": { - "version": "0.41.6", - "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.41.6.tgz", - "integrity": "sha512-HJ1fJaGlsmJGkpC4ObidtpFbdzS3umHPuuSZP46WOxgvVMNyos8QwTr6jhETxTu/eyMC7witqidpoeDta/XiIw==", + "version": "0.45.3", + "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.45.3.tgz", + "integrity": "sha512-FUjqrNsY7mfy9jAmYb23bVrgOjAeDdnKHRyT2KA8XYDOEegGPvVUgYtInYNGGzcWfiHXShO426aWB1lMcdg5cA==", "dev": true, "requires": { "@rokucommunity/bslib": "^0.1.1", @@ -6927,7 +6930,7 @@ "moment": "^2.23.0", "p-settle": "^2.1.0", "parse-ms": "^2.1.0", - "roku-deploy": "^3.5.0", + "roku-deploy": "^3.5.3", "serialize-error": "^7.0.1", "source-map": "^0.7.3", "vscode-languageserver": "7.0.0", @@ -8807,9 +8810,9 @@ } }, "luxon": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.26.0.tgz", - "integrity": "sha512-+V5QIQ5f6CDXQpWNICELwjwuHdqeJM1UenlZWx5ujcRMc9venvluCjFb4t5NYLhb6IhkbMVOxzVuOqkgMxee2A==", + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.0.tgz", + "integrity": "sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ==", "dev": true }, "make-dir": { @@ -9768,9 +9771,9 @@ } }, "roku-deploy": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.5.2.tgz", - "integrity": "sha512-W5Dfc/V7m0MdvQoYOA2PzxC5EGfyZTIjqWomGGKfkPPEwO1L5n7OP4o8Yga42z4c0u0K68yuuSQu20xwgj5d9g==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.5.3.tgz", + "integrity": "sha512-a9J6aI2ASCYkDS7FrKSRre532nIXTdhJIOAxHqlWUC692OHlUpMDmQXBPujWX7geNQSG9Y/uJkHNbE+dJVAqgw==", "requires": { "chalk": "^2.4.2", "dateformat": "^3.0.3", @@ -10420,9 +10423,9 @@ } }, "vscode-languageserver-textdocument": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz", - "integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.4.tgz", + "integrity": "sha512-/xhqXP/2A2RSs+J8JNXpiiNVvvNM0oTosNVmQnunlKvq9o4mupHOBAnnzH0lwIPKazXKvAKsVp1kr+H/K4lgoQ==", "dev": true }, "vscode-languageserver-types": { diff --git a/package.json b/package.json index ab1b939..eae2d0d 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "@typescript-eslint/eslint-plugin": "^4.4.1", "@typescript-eslint/parser": "^4.4.1", "auto-changelog": "^2.2.1", - "brighterscript": "^0.41.6", + "brighterscript": "0.45.3", "chai": "^4.2.0", "eslint": "^7.11.0", "eslint-plugin-github": "^4.1.1", @@ -39,6 +39,9 @@ "ts-node": "^10.4.0", "typescript": "^4.1.3" }, + "peerDependencies": { + "brighterscript": "^0.45.3" + }, "preferGlobal": true, "keywords": [ "brightscript", diff --git a/scripts/run.js b/scripts/run.js index c639d15..323767d 100755 --- a/scripts/run.js +++ b/scripts/run.js @@ -542,14 +542,83 @@ let maestroSample = { 'retainStagingFolder': true }; -let nba = { +// let nba = { +// 'rootDir': '/home/george/hope/nba/nba-roku/src', +// 'stagingFolderPath': 'build', +// 'plugins': [ +// '/home/george/hope/open-source/maestro/maestro-roku-bsc-plugin/dist/plugin.js', +// '/home/george/hope/open-source/rooibos/bsc-plugin/dist/plugin.js' +// ], +// 'files': [ +// 'manifest', +// 'source/**/*.*', +// 'images/**/*.*', +// 'sounds/**/*.*', +// 'sounds/*.*', +// 'fonts/**/*.*', +// 'meta/**/*.*', +// 'components/**/*.*', +// { 'src': '../src-dev/source/**/*.*', 'dest': 'source' } +// ], +// 'autoImportComponentScript': true, +// 'createPackage': false, +// 'diagnosticFilters': [ +// { +// 'src': '**/roku_modules/**/*.*' +// }, +// { +// 'src': '**/RALETrackerTask.*' +// }, +// { +// 'src': '**/*spec.bs', +// 'codes': ['LINT3011'] +// }, +// { +// 'src': '**/bitmovinAnalytics/**/*.*' +// }, +// { +// 'src': '**/bitmovinPlayer/**/*.*' +// }, +// { +// 'src': '**/mediakind/**/*.*' +// } +// ], +// 'maestro': { +// 'excludeFilters': [ +// '**/roku_modules/**/*', +// '**/roku_modules/**/*', +// '**/rooibos/**/*', +// '**/bitmovinAnalytics/**/*.*', +// '**/bitmovinPlayer/**/*.*', +// '**/mediakind/**/*.*', +// '**/NewRelicAgent/**/*.*', +// '**/NewRelicAgent.brs' +// ], +// 'buildForIDE': false, +// 'extraValidation': { +// 'doExtraValidation': true, +// 'doExtraImportValidation': true +// } +// }, +// 'rooibos': { +// 'isRecordingCodeCoverage': false, +// 'testsFilePattern': null +// }, +// 'rokuLog': { +// 'strip': false, +// 'insertPkgPath': true, +// 'removeComments': true +// }, +// 'logLevel': 'error', +// 'retainStagingFolder': true +// }; + + +let nbaLatest = { 'rootDir': '/home/george/hope/nba/nba-roku/src', 'stagingFolderPath': 'build', - 'plugins': [ - '/home/george/hope/open-source/maestro/maestro-roku-bsc-plugin/dist/plugin.js', - '/home/george/hope/open-source/rooibos/bsc-plugin/dist/plugin.js' - ], 'files': [ + '!**/*.i8n.json', 'manifest', 'source/**/*.*', 'images/**/*.*', @@ -566,6 +635,9 @@ let nba = { { 'src': '**/roku_modules/**/*.*' }, + { + 'src': '**/rooibos/**/*.*' + }, { 'src': '**/RALETrackerTask.*' }, @@ -581,12 +653,23 @@ let nba = { }, { 'src': '**/mediakind/**/*.*' + }, + { + 'src': '**/NewRelicAgent/**/*.*' + }, + { + 'src': '**/NewRelicAgent.brs' } ], + 'plugins': [ + '/home/george/hope/open-source/maestro/maestro-roku-bsc-plugin/dist/plugin.js', + '/home/george/hope/open-source/maestro/roku-log-bsc-plugin/dist/plugin.js', + '/home/george/hope/open-source/rooibos/bsc-plugin/dist/plugin.js' + ], 'maestro': { 'excludeFilters': [ '**/roku_modules/**/*', - '**/roku_modules/**/*', + '**/node_modules/**/*', '**/rooibos/**/*', '**/bitmovinAnalytics/**/*.*', '**/bitmovinPlayer/**/*.*', @@ -594,10 +677,11 @@ let nba = { '**/NewRelicAgent/**/*.*', '**/NewRelicAgent.brs' ], - 'buildForIDE': true, + 'buildForIDE': false, 'extraValidation': { 'doExtraValidation': true, - 'doExtraImportValidation': true + 'doExtraImportValidation': true, + 'excludeFilters': [] } }, 'rooibos': { @@ -610,17 +694,20 @@ let nba = { 'removeComments': true }, 'logLevel': 'error', - 'retainStagingFolder': true + 'retainStagingFolder': true, + 'transpileOptions': { + 'removeParameterTypes': true + } }; - let programBuilder = new ProgramBuilder(); programBuilder.run( // swv // zapp // maestro // corco - nba + nbaLatest + // nba // z41 // maestroSample // maestroList diff --git a/src/lib/Utils.ts b/src/lib/Utils.ts index 6b2a4e0..9e19a02 100644 --- a/src/lib/Utils.ts +++ b/src/lib/Utils.ts @@ -1,6 +1,8 @@ import type { BrsFile, ClassMethodStatement, ClassStatement, Expression, FunctionStatement, LiteralExpression, Statement } from 'brighterscript'; +import { createVariableExpression } from 'brighterscript'; -import { Position, isImportStatement, ImportStatement, isAALiteralExpression, isArrayLiteralExpression, isCommentStatement, isIntegerType, isLiteralBoolean, isLiteralNumber, isLiteralString, isLongIntegerType, isUnaryExpression, BinaryExpression, Block, createIdentifier, createStringLiteral, createToken, isClassMethodStatement, isClassStatement, Lexer, ParseMode, Parser, TokenKind, Range, IfStatement } from 'brighterscript'; +// eslint-disable-next-line @typescript-eslint/no-duplicate-imports +import * as brighterscript from 'brighterscript'; import * as rokuDeploy from 'roku-deploy'; import { createRange } from './utils/Utils'; @@ -55,8 +57,8 @@ export function pad(pad: string, str: string, padLeft: number): string { } export function makeASTFunction(source: string): FunctionStatement | undefined { - let tokens = Lexer.scan(source).tokens; - let { statements } = Parser.parse(tokens, { mode: ParseMode.BrighterScript }); + let tokens = brighterscript.Lexer.scan(source).tokens; + let { statements } = brighterscript.Parser.parse(tokens, { mode: brighterscript.ParseMode.BrighterScript }); if (statements && statements.length > 0) { return statements[0] as FunctionStatement; } @@ -85,7 +87,7 @@ export function addOverriddenMethod(target: ClassStatement, name: string, source end function end class `); - if (isClassStatement(statement)) { + if (brighterscript.isClassStatement(statement)) { let classStatement = statement as ClassStatement; target.body.push(classStatement.methods[0]); return true; @@ -95,7 +97,7 @@ export function addOverriddenMethod(target: ClassStatement, name: string, source export function changeClassMethodBody(target: ClassStatement, name: string, source: Statement[] | string): boolean { let method = target.methods.find((m) => m.name.text === name); - if (isClassMethodStatement(method)) { + if (brighterscript.isClassMethodStatement(method)) { changeFunctionBody(method, source); return true; } @@ -106,31 +108,31 @@ export function sanitizeBsJsonString(text: string) { return `"${text ? text.replace(/"/g, '\'') : ''}"`; } -export function createIfStatement(condition: Expression, statements: Statement[]): IfStatement { - let ifToken = createToken(TokenKind.If, 'if', Range.create(1, 1, 1, 999999)); - let thenBranch = new Block(statements, Range.create(1, 1, 1, 1)); - return new IfStatement({ if: ifToken, then: createToken(TokenKind.Then, '', Range.create(1, 1, 1, 999999)) }, condition, thenBranch); +export function createIfStatement(condition: Expression, statements: Statement[]): brighterscript.IfStatement { + let ifToken = brighterscript.createToken(brighterscript.TokenKind.If, 'if', brighterscript.Range.create(1, 1, 1, 999999)); + let thenBranch = new brighterscript.Block(statements, brighterscript.Range.create(1, 1, 1, 1)); + return new brighterscript.IfStatement({ if: ifToken, then: brighterscript.createToken(brighterscript.TokenKind.Then, '', brighterscript.Range.create(1, 1, 1, 999999)) }, condition, thenBranch); } -export function createVarExpression(varName: string, operator: TokenKind, value: string): BinaryExpression { - let variable = createIdentifier(varName, Range.create(1, 1, 1, 999999)); - let v = createStringLiteral(value, Range.create(1, 1, 1, 999999)); +export function createVarExpression(varName: string, operator: brighterscript.TokenKind, value: string): brighterscript.BinaryExpression { + let variable = createVariableExpression(varName, brighterscript.Range.create(1, 1, 1, 999999)); + let v = brighterscript.createStringLiteral(value, brighterscript.Range.create(1, 1, 1, 999999)); - let t = createToken(operator, getTokenText(operator), Range.create(1, 1, 1, 999999)); - return new BinaryExpression(variable, t, v); + let t = brighterscript.createToken(operator, getTokenText(operator), brighterscript.Range.create(1, 1, 1, 999999)); + return new brighterscript.BinaryExpression(variable, t, v); } -export function getTokenText(operator: TokenKind): string { +export function getTokenText(operator: brighterscript.TokenKind): string { switch (operator) { - case TokenKind.Equal: + case brighterscript.TokenKind.Equal: return '='; - case TokenKind.Plus: + case brighterscript.TokenKind.Plus: return '+'; - case TokenKind.Minus: + case brighterscript.TokenKind.Minus: return '-'; - case TokenKind.Less: + case brighterscript.TokenKind.Less: return '<'; - case TokenKind.Greater: + case brighterscript.TokenKind.Greater: return '>'; default: return ''; @@ -174,28 +176,28 @@ export function expressionToString(expr: Expression): string { if (!expr) { return 'invalid'; } - if (isUnaryExpression(expr) && isLiteralNumber(expr.right)) { + if (brighterscript.isUnaryExpression(expr) && brighterscript.isLiteralNumber(expr.right)) { return numberExpressionToValue(expr.right, expr.operator.text).toString(); } - if (isLiteralString(expr)) { + if (brighterscript.isLiteralString(expr)) { //remove leading and trailing quotes return `"${expr.token.text.replace(/^"/, '').replace(/"$/, '')}"`; } - if (isLiteralNumber(expr)) { + if (brighterscript.isLiteralNumber(expr)) { return numberExpressionToValue(expr).toString(); } - if (isLiteralBoolean(expr)) { + if (brighterscript.isLiteralBoolean(expr)) { return expr.token.text.toLowerCase() === 'true' ? 'true' : 'false'; } - if (isArrayLiteralExpression(expr)) { + if (brighterscript.isArrayLiteralExpression(expr)) { return `[${expr.elements - .filter(e => !isCommentStatement(e)) + .filter(e => !brighterscript.isCommentStatement(e)) .map(e => expressionToString(e))}]`; } - if (isAALiteralExpression(expr)) { + if (brighterscript.isAALiteralExpression(expr)) { let text = `{${expr.elements.reduce((acc, e) => { - if (!isCommentStatement(e)) { + if (!brighterscript.isCommentStatement(e)) { const sep = acc === '' ? '' : ', '; acc += `${sep}${e.keyToken.text}: ${expressionToString(e.value)}`; } @@ -209,28 +211,28 @@ export function expressionToValue(expr: Expression): any | undefined { if (!expr) { return undefined; } - if (isUnaryExpression(expr) && isLiteralNumber(expr.right)) { + if (brighterscript.isUnaryExpression(expr) && brighterscript.isLiteralNumber(expr.right)) { return numberExpressionToValue(expr.right, expr.operator.text); } - if (isLiteralString(expr)) { + if (brighterscript.isLiteralString(expr)) { //remove leading and trailing quotes return expr.token.text.replace(/^"/, '').replace(/"$/, ''); } - if (isLiteralNumber(expr)) { + if (brighterscript.isLiteralNumber(expr)) { return numberExpressionToValue(expr); } - if (isLiteralBoolean(expr)) { + if (brighterscript.isLiteralBoolean(expr)) { return expr.token.text.toLowerCase() === 'true'; } - if (isArrayLiteralExpression(expr)) { + if (brighterscript.isArrayLiteralExpression(expr)) { return expr.elements - .filter(e => !isCommentStatement(e)) + .filter(e => !brighterscript.isCommentStatement(e)) .map(e => expressionToValue(e)); } - if (isAALiteralExpression(expr)) { + if (brighterscript.isAALiteralExpression(expr)) { return expr.elements.reduce((acc, e) => { - if (!isCommentStatement(e)) { + if (!brighterscript.isCommentStatement(e)) { acc[e.keyToken.text] = expressionToValue(e.value); } return acc; @@ -240,23 +242,23 @@ export function expressionToValue(expr: Expression): any | undefined { } function numberExpressionToValue(expr: LiteralExpression, operator = '') { - if (isIntegerType(expr.type) || isLongIntegerType(expr.type)) { + if (brighterscript.isIntegerType(expr.type) || brighterscript.isLongIntegerType(expr.type)) { return parseInt(operator + expr.token.text); } else { return parseFloat(operator + expr.token.text); } } -export function createImportStatement(pkgPath: string, range: Range) { - let importToken = createToken(TokenKind.Import, 'import', range); - let filePathToken = createToken(TokenKind.SourceFilePathLiteral, `"${pkgPath}"`, range); - return new ImportStatement(importToken, filePathToken); +export function createImportStatement(pkgPath: string, range: brighterscript.Range) { + let importToken = brighterscript.createToken(brighterscript.TokenKind.Import, 'import', range); + let filePathToken = brighterscript.createToken(brighterscript.TokenKind.SourceFilePathLiteral, `"${pkgPath}"`, range); + return new brighterscript.ImportStatement(importToken, filePathToken); } export function addImport(file: BrsFile, pkgPath: string) { - let existingImports = file.parser.ast.statements.find((el) => isImportStatement(el) && el.filePath === pkgPath); + let existingImports = file.parser.ast.statements.find((el) => brighterscript.isImportStatement(el) && el.filePath === pkgPath); if (!existingImports) { - let importStatement = createImportStatement(pkgPath, createRange(Position.create(1, 1))); + let importStatement = createImportStatement(pkgPath, createRange(brighterscript.Position.create(1, 1))); file.parser.ast.statements = [importStatement, ...file.parser.ast.statements]; file.parser.invalidateReferences(); file.ownScriptImports.push({ diff --git a/src/lib/binding/BindingProcessor.ts b/src/lib/binding/BindingProcessor.ts index b04d856..9a48916 100644 --- a/src/lib/binding/BindingProcessor.ts +++ b/src/lib/binding/BindingProcessor.ts @@ -145,7 +145,12 @@ end function\n`; pathAbsolute: file.fullPath, source: file.bscFile.fileContents }; - file.bscFile.parse(fileContents.source); + + let xmlFile = file.bscFile as XmlFile; + xmlFile.parse(fileContents.source); + // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression + xmlFile.ast.component?.setAttribute('vm', undefined); + xmlFile.needsTranspiled = true; file.bindings = this.processElements(file); } diff --git a/src/lib/files/File.ts b/src/lib/files/File.ts index a8ff8ff..96028bd 100644 --- a/src/lib/files/File.ts +++ b/src/lib/files/File.ts @@ -134,6 +134,7 @@ export class File { if (this.vmClassName) { // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression xmlFile.ast.component?.setAttribute('vm', undefined); + xmlFile.needsTranspiled = true; } if (this.componentName && this.parentComponentName) { diff --git a/src/lib/importSupport/ImportProcessor.spec.ts b/src/lib/importSupport/ImportProcessor.spec.ts index 8f99e8b..d95c3fc 100644 --- a/src/lib/importSupport/ImportProcessor.spec.ts +++ b/src/lib/importSupport/ImportProcessor.spec.ts @@ -16,7 +16,7 @@ describe('build time imports', () => { it('adds build time imports', () => { let program = new Program({}); - program.addOrReplaceFile('source/AuthManager.bs', ` + program.setFile('source/AuthManager.bs', ` class someClass end class `); @@ -37,7 +37,7 @@ end function`); it('empty build time imports', () => { let program = new Program({}); - program.addOrReplaceFile('source/AuthManager.bs', ` + program.setFile('source/AuthManager.bs', ` class someClass end class `); diff --git a/src/lib/importSupport/ImportProcessor.ts b/src/lib/importSupport/ImportProcessor.ts index 78ad744..cbbb618 100644 --- a/src/lib/importSupport/ImportProcessor.ts +++ b/src/lib/importSupport/ImportProcessor.ts @@ -48,6 +48,11 @@ export default class ImportProcessor { file.parser.ast.statements = file.parser.ast.statements.filter((el) => !statementsToRemove.includes(el)); file.parser.ast.statements = statementsToAdd.concat(file.parser.ast.statements); file.parser.invalidateReferences(); + file.parser.ast.statements = file.parser.ast.statements.filter((el) => !statementsToRemove.includes(el)); + file.ownScriptImports = []; + //FIXME - remove this when Bron updates bsc + // eslint-disable-next-line @typescript-eslint/dot-notation + file['registerImports']?.(); } } } diff --git a/src/lib/node-classes/NodeClass.ts b/src/lib/node-classes/NodeClass.ts index 860134d..2ea21a0 100644 --- a/src/lib/node-classes/NodeClass.ts +++ b/src/lib/node-classes/NodeClass.ts @@ -62,7 +62,7 @@ export class NodeField { `; if (this.isRootOnlyObserver) { text += `v = event.getData() - if (type(v) <> "roSGNode" or not v.isSameNode(m._p_${this.name}) + if type(v) <> "roSGNode" or not v.isSameNode(m._p_${this.name}) m._p_${this.name} = v ${code} end if diff --git a/src/lib/reflection/ReflectionUtil.ts b/src/lib/reflection/ReflectionUtil.ts index 39dce8f..e3b2526 100644 --- a/src/lib/reflection/ReflectionUtil.ts +++ b/src/lib/reflection/ReflectionUtil.ts @@ -19,11 +19,13 @@ export default class ReflectionUtil { } public updateRuntimeFile() { - let runtimeFile = this.builder.program.getFileByPkgPath('source/roku_modules/maestro/reflection/Reflection.brs'); + let runtimeFile = this.builder.program.getFile('source/roku_modules/maestro/reflection/Reflection.brs'); if (runtimeFile) { runtimeFile.needsTranspiled = true; this.updateClassLookupFunction(runtimeFile); this.updateXMLCompTypesFunction(runtimeFile); + // eslint-disable-next-line @typescript-eslint/dot-notation + runtimeFile['diagnostics'] = []; } } diff --git a/src/lib/utils/Utils.ts b/src/lib/utils/Utils.ts index 575509b..8127e59 100644 --- a/src/lib/utils/Utils.ts +++ b/src/lib/utils/Utils.ts @@ -1,5 +1,7 @@ import type { Position, BrsFile, XmlFile, ClassStatement, FunctionStatement, ClassMethodStatement, Statement, Expression } from 'brighterscript'; -import { Range, TokenKind, isClassMethodStatement, isClassStatement, Parser, Lexer, ParseMode, Block, createToken, createIdentifier, createStringLiteral, BinaryExpression, IfStatement } from 'brighterscript'; +import { createVariableExpression } from 'brighterscript'; +// eslint-disable-next-line @typescript-eslint/no-duplicate-imports +import * as brighterscript from 'brighterscript'; import type { File } from '../files/File'; import type { ProjectFileMap } from '../files/ProjectFileMap'; @@ -84,12 +86,12 @@ export function getAssociatedFile(file: BrsFile | XmlFile, fileMap: ProjectFileM } export function createRange(pos: Position) { - return Range.create(pos.line, pos.character, pos.line, pos.character); + return brighterscript.Range.create(pos.line, pos.character, pos.line, pos.character); } export function makeASTFunction(source: string): FunctionStatement | undefined { - let tokens = Lexer.scan(source).tokens; - let { statements } = Parser.parse(tokens, { mode: ParseMode.BrighterScript }); + let tokens = brighterscript.Lexer.scan(source).tokens; + let { statements } = brighterscript.Parser.parse(tokens, { mode: brighterscript.ParseMode.BrighterScript }); if (statements && statements.length > 0) { return statements[0] as FunctionStatement; } @@ -118,7 +120,7 @@ export function addOverriddenMethod(target: ClassStatement, name: string, source end function end class `); - if (isClassStatement(statement)) { + if (brighterscript.isClassStatement(statement)) { let classStatement = statement as ClassStatement; target.body.push(classStatement.methods[0]); return true; @@ -128,7 +130,7 @@ export function addOverriddenMethod(target: ClassStatement, name: string, source export function changeClassMethodBody(target: ClassStatement, name: string, source: string): boolean { let method = target.methods.find((m) => m.name.text === name); - if (isClassMethodStatement(method)) { + if (brighterscript.isClassMethodStatement(method)) { changeFunctionBody(method, source); return true; } @@ -139,39 +141,39 @@ export function sanitizeBsJsonString(text: string) { return `"${text ? text.replace(/"/g, '\'') : ''}"`; } -export function createIfStatement(condition: Expression, statements: Statement[]): IfStatement { - let ifToken = createToken(TokenKind.If, 'else if', Range.create(1, 1, 1, 999999)); +export function createIfStatement(condition: Expression, statements: Statement[]): brighterscript.IfStatement { + let ifToken = brighterscript.createToken(brighterscript.TokenKind.If, 'else if', brighterscript.Range.create(1, 1, 1, 999999)); ifToken.text = 'else if'; - let thenBranch = new Block(statements, Range.create(1, 1, 1, 1)); - return new IfStatement({ if: ifToken, then: createToken(TokenKind.Then, '', Range.create(1, 1, 1, 999999)) }, condition, thenBranch); + let thenBranch = new brighterscript.Block(statements, brighterscript.Range.create(1, 1, 1, 1)); + return new brighterscript.IfStatement({ if: ifToken, then: brighterscript.createToken(brighterscript.TokenKind.Then, '', brighterscript.Range.create(1, 1, 1, 999999)) }, condition, thenBranch); } -export function createVarExpression(varName: string, operator: TokenKind, value: string): BinaryExpression { - let variable = createIdentifier(varName, Range.create(1, 1, 1, 999999)); - let v = createStringLiteral('"' + value, Range.create(1, 1, 1, 999999)); +export function createVarExpression(varName: string, operator: brighterscript.TokenKind, value: string): brighterscript.BinaryExpression { + let variable = createVariableExpression(varName, brighterscript.Range.create(1, 1, 1, 999999)); + let v = brighterscript.createStringLiteral('"' + value, brighterscript.Range.create(1, 1, 1, 999999)); - let t = createToken(operator, getTokenText(operator), Range.create(1, 1, 1, 999999)); - return new BinaryExpression(variable, t, v); + let t = brighterscript.createToken(operator, getTokenText(operator), brighterscript.Range.create(1, 1, 1, 999999)); + return new brighterscript.BinaryExpression(variable, t, v); } -export function getTokenText(operator: TokenKind): string { +export function getTokenText(operator: brighterscript.TokenKind): string { switch (operator) { - case TokenKind.Equal: + case brighterscript.TokenKind.Equal: return '='; - case TokenKind.Plus: + case brighterscript.TokenKind.Plus: return '+'; - case TokenKind.Minus: + case brighterscript.TokenKind.Minus: return '-'; - case TokenKind.Less: + case brighterscript.TokenKind.Less: return '<'; - case TokenKind.Greater: + case brighterscript.TokenKind.Greater: return '>'; default: return '>'; } } -export function getAllFields(fileMap: ProjectFileMap, cs: ClassStatement, vis?: TokenKind) { +export function getAllFields(fileMap: ProjectFileMap, cs: ClassStatement, vis?: brighterscript.TokenKind) { let result = {}; while (cs) { for (let field of cs.fields) { @@ -179,13 +181,13 @@ export function getAllFields(fileMap: ProjectFileMap, cs: ClassStatement, vis?: result[field.name.text.toLowerCase()] = field; } } - cs = cs.parentClassName ? fileMap.allClasses.get(cs.parentClassName.getName(ParseMode.BrighterScript).replace(/_/g, '.')) : null; + cs = cs.parentClassName ? fileMap.allClasses.get(cs.parentClassName.getName(brighterscript.ParseMode.BrighterScript).replace(/_/g, '.')) : null; } return result; } -export function getAllMethods(fileMap: ProjectFileMap, cs: ClassStatement, vis?: TokenKind) { +export function getAllMethods(fileMap: ProjectFileMap, cs: ClassStatement, vis?: brighterscript.TokenKind) { let result = {}; while (cs) { for (let method of cs.methods) { @@ -193,7 +195,7 @@ export function getAllMethods(fileMap: ProjectFileMap, cs: ClassStatement, vis?: result[method.name.text.toLowerCase()] = method; } } - cs = cs.parentClassName ? fileMap.allClasses.get(cs.parentClassName.getName(ParseMode.BrighterScript).replace(/_/g, '.')) : null; + cs = cs.parentClassName ? fileMap.allClasses.get(cs.parentClassName.getName(brighterscript.ParseMode.BrighterScript).replace(/_/g, '.')) : null; } return result; @@ -207,7 +209,7 @@ export function getAllAnnotations(fileMap: ProjectFileMap, cs: ClassStatement) { result[annotation.name.toLowerCase()] = true; } } - cs = cs.parentClassName ? fileMap.allClasses.get(cs.parentClassName.getName(ParseMode.BrighterScript).replace(/_/g, '.')) : null; + cs = cs.parentClassName ? fileMap.allClasses.get(cs.parentClassName.getName(brighterscript.ParseMode.BrighterScript).replace(/_/g, '.')) : null; } return result; diff --git a/src/plugin.spec.ts b/src/plugin.spec.ts index 65e391c..3bc725d 100644 --- a/src/plugin.spec.ts +++ b/src/plugin.spec.ts @@ -28,8 +28,15 @@ describe('MaestroPlugin', () => { options = { rootDir: _rootDir, stagingFolderPath: _stagingFolderPath, + autoImportComponentScript: true + }; + options.maestro = { mvvm: {}, - nodeClasses: {} + nodeClasses: {}, + processXMLFiles: true, + buildTimeImports: { + 'IAuthProvider': ['pkg:/source/AuthManager.bs'] + } }; fsExtra.ensureDirSync(_stagingFolderPath); fsExtra.ensureDirSync(_rootDir); @@ -45,10 +52,14 @@ describe('MaestroPlugin', () => { extraValidation: {}, addFrameworkFiles: false, mvvm: {}, - nodeClasses: {} + processXMLFiles: true, + nodeClasses: {}, + buildTimeImports: { + 'IAuthProvider': ['pkg:/source/AuthManager.bs'] + } }; plugin.beforeProgramCreate(builder); - program.addOrReplaceFile('manifest', ``); + program.setFile('manifest', ``); }); afterEach(() => { @@ -64,17 +75,17 @@ describe('MaestroPlugin', () => { it('gives error diagnostics when field bindings do not match class', async () => { plugin.isFrameworkAdded = true; plugin.afterProgramCreate(program); - program.addOrReplaceFile('source/comp.bs', ` + program.setFile('source/comp.bs', ` class myVM function onChangeVisible(value) end function end class `); - program.addOrReplaceFile('components/comp.brs', ` + program.setFile('components/comp.brs', ` `); - program.addOrReplaceFile('components/comp.xml', ` + program.setFile('components/comp.xml', ` @@ -108,18 +119,18 @@ describe('MaestroPlugin', () => { it('does not give diagnostics for valid target bindings', async () => { plugin.afterProgramCreate(program); - program.addOrReplaceFile('source/comp.bs', ` + program.setFile('source/comp.bs', ` class myVM public isClicked function onChangeVisible(value = invalid, node = invalid) end function end class `); - program.addOrReplaceFile('components/comp.brs', ` + program.setFile('components/comp.brs', ` `); - program.addOrReplaceFile('components/comp.xml', ` + program.setFile('components/comp.xml', ` @@ -147,17 +158,17 @@ describe('MaestroPlugin', () => { it('gives diagnostics when trying to set a function call back as a field', async () => { plugin.afterProgramCreate(program); - program.addOrReplaceFile('source/comp.bs', ` + program.setFile('source/comp.bs', ` class myVM function onChangeVisible(value) end function end class `); - program.addOrReplaceFile('components/comp.brs', ` + program.setFile('components/comp.brs', ` `); - program.addOrReplaceFile('components/comp.xml', ` + program.setFile('components/comp.xml', ` @@ -181,18 +192,18 @@ describe('MaestroPlugin', () => { }); it('gives error diagnostics when id is not set', async () => { plugin.afterProgramCreate(program); - program.addOrReplaceFile('source/comp.bs', ` + program.setFile('source/comp.bs', ` class myVM public text function onChangeVisible(value) end function end class `); - program.addOrReplaceFile('components/comp.brs', ` + program.setFile('components/comp.brs', ` `); - program.addOrReplaceFile('components/comp.xml', ` + program.setFile('components/comp.xml', ` @@ -216,18 +227,18 @@ describe('MaestroPlugin', () => { it('takes optional params into account', async () => { plugin.afterProgramCreate(program); - program.addOrReplaceFile('source/comp.bs', ` + program.setFile('source/comp.bs', ` class myVM public isClicked function onChangeVisible(value = invalid, node = invalid) end function end class `); - program.addOrReplaceFile('components/comp.brs', ` + program.setFile('components/comp.brs', ` `); - program.addOrReplaceFile('components/comp.xml', ` + program.setFile('components/comp.xml', ` @@ -254,21 +265,21 @@ describe('MaestroPlugin', () => { it('inserts static bindings', async () => { plugin.afterProgramCreate(program); - program.addOrReplaceFile('source/vm.bs', ` + program.setFile('source/vm.bs', ` class myVM public riversJson public entry end class `); - program.addOrReplaceFile('components/comp.bs', ` + program.setFile('components/comp.bs', ` class myVM public riversJson public entry end class `); - program.addOrReplaceFile('components/comp.xml', ` + program.setFile('components/comp.xml', ` @@ -346,18 +357,18 @@ describe('MaestroPlugin', () => { it('warns when field bindings are not public', async () => { plugin.afterProgramCreate(program); - program.addOrReplaceFile('source/comp.bs', ` + program.setFile('source/comp.bs', ` class myVM private width private function onChangeVisible(value) end function end class `); - program.addOrReplaceFile('components/comp.brs', ` + program.setFile('components/comp.brs', ` `); - program.addOrReplaceFile('components/comp.xml', ` + program.setFile('components/comp.xml', ` @@ -382,7 +393,7 @@ describe('MaestroPlugin', () => { it('does not manipulate non binding xml files', async () => { plugin.afterProgramCreate(program); - program.addOrReplaceFile('components/comp.xml', ` + program.setFile('components/comp.xml', ` @@ -405,7 +416,7 @@ describe('MaestroPlugin', () => { }); it('does removes vm tags from files files', async () => { plugin.afterProgramCreate(program); - program.addOrReplaceFile('components/comp.xml', ` + program.setFile('components/comp.xml', ` @@ -432,7 +443,7 @@ describe('MaestroPlugin', () => { it('does not manipulate xml files that are in default ignored folders (roku_modules)', async () => { plugin.afterProgramCreate(program); - program.addOrReplaceFile('components/roku_modules/mv/comp.xml', ` + program.setFile('components/roku_modules/mv/comp.xml', ` @@ -463,7 +474,7 @@ describe('MaestroPlugin', () => { it('does not manipulate xml files when xml processing is disabled', async () => { plugin.maestroConfig.processXMLFiles = false; plugin.afterProgramCreate(program); - program.addOrReplaceFile('components/comp.xml', ` + program.setFile('components/comp.xml', ` @@ -503,7 +514,7 @@ describe('MaestroPlugin', () => { plugin.importProcessor.config = plugin.maestroConfig; plugin.afterProgramCreate(program); - program.addOrReplaceFile('components/roku_modules/mv/comp.xml', ` + program.setFile('components/roku_modules/mv/comp.xml', ` @@ -541,7 +552,7 @@ describe('MaestroPlugin', () => { plugin.importProcessor.config = plugin.maestroConfig; plugin.afterProgramCreate(program); - program.addOrReplaceFile('components/ignored/mv/comp.xml', ` + program.setFile('components/ignored/mv/comp.xml', ` @@ -574,7 +585,7 @@ describe('MaestroPlugin', () => { it('parses a node class with no errors', async () => { plugin.afterProgramCreate(program); - program.addOrReplaceFile('source/comp.bs', ` + program.setFile('source/comp.bs', ` @node("Comp", "Group") class Comp @@ -596,6 +607,8 @@ describe('MaestroPlugin', () => { +