@quintaaa/eslint-plugin-starlims
Version:
Eslint plugin to parse and lint starlims form code successfully
92 lines (89 loc) • 3.21 kB
JavaScript
module.exports = {
meta: {
type: 'problem',
docs: {
description:
'Detect requests in looops like lims.CallServer() or lims.GetDataSet()',
recommended: true,
},
},
create(context) {
const synchronousRequests = [
'CallServer',
'GetDataSet',
'GetData',
'GetDataSource', // Technically not sending a request, but does when used with dgd.Data = lims.GetDataSource() (99% of the time)
];
const asyncRequests = [
'CallServerAsync',
'GetDataSetAsync',
'GetDataAsync',
];
return {
CallExpression(node) {
if (
node.callee?.object?.name === 'lims' &&
synchronousRequests
.concat(asyncRequests)
.includes(node.callee?.property?.name)
) {
if (isInLoop(node) || isInArrayLoop(node)) {
if (
asyncRequests.includes(node.callee.property.name) &&
node.parent.type !== 'AwaitExpression'
)
return;
let message;
if (asyncRequests.includes(node.callee.property.name))
message =
'Avoid awaiting requests in loops ({{ function }}). You should either make a server script or datasource that allows you to retrieve the data in one request or do not await each call (Using Promise.all if possible or handling the response in a callback).';
else
message =
'Avoid requests in loops ({{ function }}). You should make a server script or datasource that allows you to retrieve the data in one request. Or call the asynchronous version of the function and handle the result afterwards.';
context.report({
node,
message,
data: {
function: node.callee.property.name,
},
});
}
}
},
};
},
};
const isInLoop = (node) => {
if (
[
'ForStatement',
'ForInStatement',
'ForOfStatement',
'WhileStatement',
'DoWhileStatement',
].includes(node.type)
)
return true;
if (node.parent) return isInLoop(node.parent);
return false;
};
// Most used array loops
const arrayLoops = [
'forEach',
'map',
'filter',
'reduce',
'reduceRight',
'every',
'some',
'find',
];
const isInArrayLoop = (node) => {
if (
node.type === 'CallExpression' &&
arrayLoops.includes(node.callee?.property?.name)
)
return true;
if (node.parent) return isInArrayLoop(node.parent);
return false;
};