rooibos-roku
Version:
simple, flexible, fun brightscript test framework for roku scenegraph apps - roku brighterscript plugin
144 lines • 6.95 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getScopeForSuite = exports.getPathValuePartAsString = exports.getStringPathFromDottedGet = exports.getRootObjectFromDottedGet = exports.getAllDottedGetParts = exports.functionRequiresReturnValue = exports.sanitizeBsJsonString = exports.addOverriddenMethod = void 0;
const brighterscript_1 = require("brighterscript");
const Diagnostics_1 = require("../utils/Diagnostics");
function addOverriddenMethod(file, annotation, target, name, source, editor) {
var _a, _b;
let { method, diagnostics, text } = createMethod(file, name, source);
if (method.func.body.statements.length > 0) {
//bsc has a quirk where it auto-adds a `new` method if missing. That messes with our AST editing, so
//trigger that functionality BEFORE performing AstEditor operations. TODO remove this whenever bsc stops doing this.
(_b = (_a = target).ensureConstructorFunctionExists) === null || _b === void 0 ? void 0 : _b.call(_a);
editor.addToArray(target.body, target.body.length, method);
return true;
}
const error = (diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.length) > 0 ? diagnostics[0].message : 'unknown error';
(0, Diagnostics_1.diagnosticCorruptTestProduced)(file, annotation, error, text);
return false;
}
exports.addOverriddenMethod = addOverriddenMethod;
/**
* Create a new MethodStatement instance with the given name and body.
*
* This is a HACK to be able to build the same MethodStatement instance as the version of brighterscript we're running against. (because otherwise, some older versions
* of bsc (like the one rooibos depends on) have a bug that doesn't transpile the method name correctly in some instances)
* @param file any file from the host program's version of BrighterScript. (we're going to utilize its `constructor` and `parse` functions to create a new MethodStatement instance)
* @param name name of the method to create
* @param body string text containing the body of the method
*/
function createMethod(file, name, body) {
const text = `
class RooibosTemplateClass
public override function ${name}()
${body}
end function
end class
`;
try {
//parse a new instance of a file, so we can abuse its `parse` function, which will use the _current_ version of the MethodStatement class
const f = new file.constructor(file.srcPath, file.pkgPath, file.program);
f.parse(text);
return {
method: f.ast.statements[0].body[0],
text: text,
diagnostics: f.diagnostics
};
}
catch (e) {
console.error(`Error generating method '${name}' while using the host bsc version. Falling back to embedded Parser.parse`, {
cause: e
});
const { statements, diagnostics } = brighterscript_1.Parser.parse(text, { mode: brighterscript_1.ParseMode.BrighterScript });
return {
method: statements[0].body[0],
text: text,
diagnostics: diagnostics
};
}
}
function sanitizeBsJsonString(text) {
return `"${text ? text.replace(/"/g, '\'') : ''}"`;
}
exports.sanitizeBsJsonString = sanitizeBsJsonString;
function functionRequiresReturnValue(statement) {
const returnTypeToken = statement.func.returnTypeToken;
const functionType = statement.func.functionType;
return !(((functionType === null || functionType === void 0 ? void 0 : functionType.kind) === brighterscript_1.TokenKind.Sub && (returnTypeToken === undefined || (returnTypeToken === null || returnTypeToken === void 0 ? void 0 : returnTypeToken.kind) === brighterscript_1.TokenKind.Void)) || (returnTypeToken === null || returnTypeToken === void 0 ? void 0 : returnTypeToken.kind) === brighterscript_1.TokenKind.Void);
}
exports.functionRequiresReturnValue = functionRequiresReturnValue;
function getAllDottedGetParts(dg) {
var _a, _b;
let parts = [(_a = dg === null || dg === void 0 ? void 0 : dg.name) === null || _a === void 0 ? void 0 : _a.text];
let nextPart = dg.obj;
while ((0, brighterscript_1.isDottedGetExpression)(nextPart) || (0, brighterscript_1.isVariableExpression)(nextPart)) {
parts.push((_b = nextPart === null || nextPart === void 0 ? void 0 : nextPart.name) === null || _b === void 0 ? void 0 : _b.text);
nextPart = (0, brighterscript_1.isDottedGetExpression)(nextPart) ? nextPart.obj : undefined;
}
return parts.reverse();
}
exports.getAllDottedGetParts = getAllDottedGetParts;
function getRootObjectFromDottedGet(value) {
let root;
if ((0, brighterscript_1.isDottedGetExpression)(value) || (0, brighterscript_1.isIndexedGetExpression)(value)) {
root = value.obj;
while (root.obj) {
root = root.obj;
}
}
else {
root = value;
}
return root;
}
exports.getRootObjectFromDottedGet = getRootObjectFromDottedGet;
function getStringPathFromDottedGet(value) {
let parts = [getPathValuePartAsString(value)];
let root;
root = value.obj;
while (root) {
if ((0, brighterscript_1.isCallExpression)(root) || (0, brighterscript_1.isCallfuncExpression)(root)) {
return undefined;
}
parts.push(`${getPathValuePartAsString(root)}`);
root = root.obj;
}
let joinedParts = parts.reverse().join('.');
return joinedParts === '' ? undefined : (0, brighterscript_1.createStringLiteral)(joinedParts);
}
exports.getStringPathFromDottedGet = getStringPathFromDottedGet;
function getPathValuePartAsString(expr) {
if ((0, brighterscript_1.isCallExpression)(expr) || (0, brighterscript_1.isCallfuncExpression)(expr)) {
return undefined;
}
if ((0, brighterscript_1.isVariableExpression)(expr)) {
return expr.name.text;
}
if (!expr) {
return undefined;
}
if ((0, brighterscript_1.isDottedGetExpression)(expr)) {
return expr.name.text;
}
else if ((0, brighterscript_1.isIndexedGetExpression)(expr)) {
if ((0, brighterscript_1.isLiteralExpression)(expr.index)) {
return `${expr.index.token.text.replace(/^"/, '').replace(/"$/, '')}`;
}
else if ((0, brighterscript_1.isVariableExpression)(expr.index)) {
return `${expr.index.name.text}`;
}
}
}
exports.getPathValuePartAsString = getPathValuePartAsString;
function getScopeForSuite(testSuite) {
if (testSuite.isNodeTest) {
return testSuite.file.program.getScopesForFile(testSuite.file).find((scope) => {
return (0, brighterscript_1.isXmlScope)(scope) && scope.xmlFile.componentName.text === testSuite.generatedNodeName;
});
}
else {
return testSuite.file.program.getFirstScopeForFile(testSuite.file);
}
}
exports.getScopeForSuite = getScopeForSuite;
//# sourceMappingURL=Utils.js.map