UNPKG

rooibos-roku

Version:

simple, flexible, fun brightscript test framework for roku scenegraph apps - roku brighterscript plugin

165 lines (164 loc) 8.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CodeCoverageProcessor = exports.CodeCoverageLineType = void 0; const brighterscript_1 = require("brighterscript"); const RawCodeStatement_1 = require("./RawCodeStatement"); const RawCodeExpression_1 = require("./RawCodeExpression"); var CodeCoverageLineType; (function (CodeCoverageLineType) { CodeCoverageLineType[CodeCoverageLineType["noCode"] = 0] = "noCode"; CodeCoverageLineType[CodeCoverageLineType["code"] = 1] = "code"; CodeCoverageLineType[CodeCoverageLineType["condition"] = 2] = "condition"; CodeCoverageLineType[CodeCoverageLineType["branch"] = 3] = "branch"; })(CodeCoverageLineType = exports.CodeCoverageLineType || (exports.CodeCoverageLineType = {})); class CodeCoverageProcessor { constructor(builder, fileFactory) { this.coverageBrsTemplate = ` function RBS_CC_#ID#_reportLine(lineNumber, reportType = 1) _rbs_ccn = m._rbs_ccn if _rbs_ccn <> invalid _rbs_ccn.entry = { "f": "#ID#", "l": lineNumber, "r": reportType } return true end if _rbs_ccn = m?.global?._rbs_ccn if _rbs_ccn <> invalid _rbs_ccn.entry = { "f": "#ID#", "l": lineNumber, "r": reportType } m._rbs_ccn = _rbs_ccn return true end if return true end function `; this.config = builder.options.rooibos || {}; this.expectedCoverageMap = {}; this.filePathMap = {}; this.fileId = 0; this.fileFactory = fileFactory; try { } catch (e) { console.log('Error:', e.stack); } } generateMetadata(isUsingCoverage, program) { this.fileFactory.createCoverageComponent(program, this.expectedCoverageMap, this.filePathMap); } addCodeCoverage(file, astEditor) { if (this.config.isRecordingCodeCoverage) { this._processFile(file, astEditor); } } _processFile(file, astEditor) { this.fileId++; this.coverageMap = new Map(); this.executableLines = new Map(); this.processedStatements = new Set(); this.addedStatements = new Set(); this.astEditor = astEditor; file.ast.walk((0, brighterscript_1.createVisitor)({ ForStatement: (ds, parent, owner, key) => { this.addStatement(ds); ds.forToken.text = `${this.getFuncCallText(ds.range.start.line, CodeCoverageLineType.code)}: for`; }, IfStatement: (ifStatement, parent, owner, key) => { var _a; this.addStatement(ifStatement); ifStatement.condition = new brighterscript_1.BinaryExpression(new RawCodeExpression_1.RawCodeExpression(this.getFuncCallText(ifStatement.condition.range.start.line, CodeCoverageLineType.condition)), (0, brighterscript_1.createToken)(brighterscript_1.TokenKind.And), new brighterscript_1.GroupingExpression({ left: (0, brighterscript_1.createToken)(brighterscript_1.TokenKind.LeftParen), right: (0, brighterscript_1.createToken)(brighterscript_1.TokenKind.RightParen) }, ifStatement.condition)); let blockStatements = (_a = ifStatement === null || ifStatement === void 0 ? void 0 : ifStatement.thenBranch) === null || _a === void 0 ? void 0 : _a.statements; if (blockStatements) { let coverageStatement = new RawCodeStatement_1.RawCodeStatement(this.getFuncCallText(ifStatement.range.start.line, CodeCoverageLineType.branch)); blockStatements.splice(0, 0, coverageStatement); } // Handle the else blocks let elseBlock = ifStatement.elseBranch; if ((0, brighterscript_1.isBlock)(elseBlock) && elseBlock.statements) { let coverageStatement = new RawCodeStatement_1.RawCodeStatement(this.getFuncCallText(elseBlock.range.start.line - 1, CodeCoverageLineType.branch)); elseBlock.statements.splice(0, 0, coverageStatement); } }, GotoStatement: (ds, parent, owner, key) => { this.addStatement(ds); this.convertStatementToCoverageStatement(ds, CodeCoverageLineType.code, owner, key); }, WhileStatement: (ds, parent, owner, key) => { ds.tokens.while.text = `${this.getFuncCallText(ds.range.start.line, CodeCoverageLineType.code)}: while`; }, ReturnStatement: (ds, parent, owner, key) => { this.addStatement(ds); this.convertStatementToCoverageStatement(ds, CodeCoverageLineType.code, owner, key); }, ForEachStatement: (ds, parent, owner, key) => { this.addStatement(ds); ds.tokens.forEach.text = `${this.getFuncCallText(ds.range.start.line, CodeCoverageLineType.code)}: for each`; }, ExitWhileStatement: (ds, parent, owner, key) => { }, PrintStatement: (ds, parent, owner, key) => { this.addStatement(ds); this.convertStatementToCoverageStatement(ds, CodeCoverageLineType.code, owner, key); }, DottedSetStatement: (ds, parent, owner, key) => { this.addStatement(ds); this.convertStatementToCoverageStatement(ds, CodeCoverageLineType.code, owner, key); }, IndexedSetStatement: (ds, parent, owner, key) => { this.addStatement(ds); this.convertStatementToCoverageStatement(ds, CodeCoverageLineType.code, owner, key); }, IncrementStatement: (ds, parent, owner, key) => { this.addStatement(ds); this.convertStatementToCoverageStatement(ds, CodeCoverageLineType.code, owner, key); }, AssignmentStatement: (ds, parent, owner, key) => { if (!(0, brighterscript_1.isForStatement)(parent)) { this.addStatement(ds); this.convertStatementToCoverageStatement(ds, CodeCoverageLineType.code, owner, key); } }, ExpressionStatement: (ds, parent, owner, key) => { this.addStatement(ds); this.convertStatementToCoverageStatement(ds, CodeCoverageLineType.code, owner, key); } }), { walkMode: brighterscript_1.WalkMode.visitAllRecursive }); const coverageMapObject = {}; for (let key of this.coverageMap.keys()) { coverageMapObject[key] = this.coverageMap.get(key); } this.expectedCoverageMap[this.fileId.toString().trim()] = coverageMapObject; this.filePathMap[this.fileId] = file.pkgPath; this.addBrsAPIText(file, astEditor); } convertStatementToCoverageStatement(statement, coverageType, owner, key) { if (this.processedStatements.has(statement) || this.addedStatements.has(statement)) { return; } const lineNumber = statement.range.start.line; this.coverageMap.set(lineNumber, coverageType); const parsed = brighterscript_1.Parser.parse(this.getFuncCallText(lineNumber, coverageType)).ast.statements[0]; this.astEditor.arraySplice(owner, key, 0, parsed); this.addedStatements.add(parsed); // store the statement in a set to avoid handling again after inserting statement above this.processedStatements.add(statement); } addBrsAPIText(file, astEditor) { const astCodeToInject = brighterscript_1.Parser.parse(this.coverageBrsTemplate.replace(/\#ID\#/g, this.fileId.toString().trim())).ast.statements; astEditor.arrayPush(file.ast.statements, ...astCodeToInject); for (let statement of astCodeToInject) { this.addedStatements.add(statement); } } addStatement(statement, lineNumber) { if (!this.executableLines.has(lineNumber)) { this.executableLines.set(lineNumber, statement); } } getFuncCallText(lineNumber, lineType) { this.coverageMap.set(lineNumber, lineType); return `RBS_CC_${this.fileId}_reportLine("${lineNumber.toString().trim()}", ${lineType.toString().trim()})`; } } exports.CodeCoverageProcessor = CodeCoverageProcessor; //# sourceMappingURL=CodeCoverageProcessor.js.map