Skip to content

Commit

Permalink
feat: create rule for no-fibers-future-usage.
Browse files Browse the repository at this point in the history
  • Loading branch information
matheusccastroo committed Dec 14, 2023
1 parent f547205 commit 2a7c96f
Show file tree
Hide file tree
Showing 2 changed files with 267 additions and 0 deletions.
177 changes: 177 additions & 0 deletions npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/**
* @fileoverview This rule checks the usage of Fibers/Future directly.
* @author Matheus Castro
* @copyright 2023 Matheus Castro. All rights reserved.
* See LICENSE file in root directory for full license.
*/

const futureMethods = [

Check failure on line 8 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Replace `⏎··"wrap",⏎··"task",⏎··"wait",⏎··"fromPromise",⏎` with `'wrap',·'task',·'wait',·'fromPromise'`

Check failure on line 8 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Replace `⏎··"wrap",⏎··"task",⏎··"wait",⏎··"fromPromise",⏎` with `'wrap',·'task',·'wait',·'fromPromise'`
"wrap",
"task",
"wait",
"fromPromise",
];

const fibersMethods = [

Check failure on line 15 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Replace `⏎··"yield",⏎··"current",⏎` with `'yield',·'current'`

Check failure on line 15 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Replace `⏎··"yield",⏎··"current",⏎` with `'yield',·'current'`
"yield",
"current",
];

const isCreatingFuture = (node) => {
const isNewExpression = node &&

Check failure on line 21 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Replace `⏎····node.type·===·"NewExpression"` with `·node.type·===·'NewExpression'`

Check failure on line 21 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Replace `⏎····node.type·===·"NewExpression"` with `·node.type·===·'NewExpression'`
node.type === "NewExpression";
if (!isNewExpression) {
return false;
}

const newExpressionCalleeName = node &&

Check failure on line 27 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Insert `⏎···`

Check failure on line 27 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Insert `⏎···`
node.callee &&
node.callee.type === "Identifier" &&

Check failure on line 29 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Replace `"Identifier"` with `'Identifier'`

Check failure on line 29 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Replace `"Identifier"` with `'Identifier'`
node.callee.name;

return newExpressionCalleeName && newExpressionCalleeName.toLowerCase() === "future";

Check failure on line 32 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Replace `·newExpressionCalleeName·&&·newExpressionCalleeName.toLowerCase()··===·"future"` with `·(⏎····newExpressionCalleeName·&&⏎····newExpressionCalleeName.toLowerCase()·===·'future'⏎··)`

Check failure on line 32 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Replace `·newExpressionCalleeName·&&·newExpressionCalleeName.toLowerCase()··===·"future"` with `·(⏎····newExpressionCalleeName·&&⏎····newExpressionCalleeName.toLowerCase()·===·'future'⏎··)`
};

const isUsingFutureMethods = (node) => {
const isMemberExpression = node &&

Check failure on line 36 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Replace `⏎····node.type·===·"MemberExpression"` with `·node.type·===·'MemberExpression'`

Check failure on line 36 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Replace `⏎····node.type·===·"MemberExpression"` with `·node.type·===·'MemberExpression'`
node.type === "MemberExpression";
if (!isMemberExpression) {
return false;
}

const nodeObjectIsFuture = node &&

Check failure on line 42 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Insert `⏎···`

Check failure on line 42 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Insert `⏎···`
node.object &&
node.object.type === "Identifier" &&

Check failure on line 44 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Replace `"Identifier"` with `'Identifier'`

Check failure on line 44 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Replace `"Identifier"` with `'Identifier'`
node.object.name &&
node.object.name.toLowerCase() === "future";

Check failure on line 46 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Replace `"future"` with `'future'`

Check failure on line 46 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js

View workflow job for this annotation

GitHub Actions / test (14.x)

Replace `"future"` with `'future'`

const nodePropertyName = node &&
node.property &&
node.property.type === "Identifier" &&
node.property.name;

return nodeObjectIsFuture && nodePropertyName && futureMethods.includes(nodePropertyName);
};

const isCallingFibers = (node) => {
const isCallExpression = node &&
node.type === "CallExpression";
if (!isCallExpression) {
return false;
}

const identifierName = node &&
node.callee &&
node.callee.type === "Identifier" &&
node.callee.name;

return identifierName && identifierName.toLowerCase() === "fiber";
};

const isUsingFibersMethods = (node) => {
const isMemberExpression = node &&
node.type === "MemberExpression";
if (!isMemberExpression) {
return false;
}

const nodeObjectIsFiber = node &&
node.object &&
node.object.type === "Identifier" &&
node.object.name &&
node.object.name.toLowerCase() === "fiber";

const propertyName = node &&
node.property &&
node.property.type === "Identifier" &&
node.property.name;

return nodeObjectIsFiber && propertyName && fibersMethods.includes(propertyName.toLowerCase());
};

const includesFibersOrFuturePath = (toTest) => toTest &&
typeof toTest === "string" &&
["fibers", "future"].some((t) => toTest.toLowerCase().includes(t));

const isImportingFibersOrFuture = (node) => {
const isImportDeclaration = node &&
node.type === "ImportDeclaration";
if (!isImportDeclaration) {
return false;
}

const nodeSourceLiteral = node &&
node.source &&
node.source.type === "Literal" &&
node.source.value;

return includesFibersOrFuturePath(nodeSourceLiteral);
};

const isRequiringFibersOrFuture = (node) => {
const isCallExpression = node &&
node.type === "CallExpression";
if (!isCallExpression) {
return false;
}

const nodeCalleeName = node &&
node.callee &&
node.callee.type === "Identifier" &&
node.callee.name;
const nodeRequirePath = node &&
node.arguments &&
node.arguments[0] &&
node.arguments[0].type === "Literal" &&
node.arguments[0].value;

return nodeCalleeName && nodeCalleeName.toLowerCase() === "require" && includesFibersOrFuturePath(nodeRequirePath);
};

const futureUsageError = "Invalid usage of Future";
const fibersUsageError = "Invalid usage of Fibers";
const fibersFutureImportError = "Invalid import/require of Fibers/Future";

module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Detect Fibers/Future usages',
recommended: true,
},
},
create: (context) => ({
ImportDeclaration: (node) => {
if (!isImportingFibersOrFuture(node)) {
return;
}

return context.report(node, fibersFutureImportError);
},
NewExpression: (node) => {
if (!isCreatingFuture(node)) {
return;
}

return context.report(node, futureUsageError);
},
CallExpression: (node) => {
if (isCallingFibers(node)) {
return context.report(node, fibersUsageError);
}

if (isRequiringFibersOrFuture(node)) {
return context.report(node, fibersFutureImportError);
}
},
MemberExpression: (node) => {
if (isUsingFibersMethods(node)) {
return context.report(node, fibersUsageError);
}

if (isUsingFutureMethods(node)) {
return context.report(node, futureUsageError);
}
},
}),
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* @fileoverview This rule checks the usage of Meteor Promise Fibers methods.
* @author Matheus Castro
* @copyright 2023 Matheus Castro. All rights reserved.
* See LICENSE file in root directory for full license.
*/

const { RuleTester } = require('eslint');
const rule = require('../../../lib/rules/no-fibers-future-usage');

const ruleTester = new RuleTester({
parserOptions: {
ecmaVersion: 2015,
sourceType: 'module',
},
});

ruleTester.run('no-fibers-future-usage', rule, {
only: true,
valid: [
{ code: 'import asd from "asd"' },
{ code: 'const asd = require("dd")' },
{ code: 'const aa = new Test()' },
{ code: 'Testing(function() {})' },
{ code: 'User.current' },
],

invalid: [
{
code: 'import Future from "fibers/future"',
errors: [
{ message: 'Invalid import/require of Fibers/Future', type: 'ImportDeclaration' },
],
},
{
code: 'require("fibers/future")',
errors: [
{ message: 'Invalid import/require of Fibers/Future', type: 'CallExpression' },
],
},
{
code: 'const asd = new Future()',
errors: [
{ message: 'Invalid usage of Future', type: 'NewExpression' },
],
},
{
code: 'Future.fromPromise(asyncValue)',
errors: [
{ message: 'Invalid usage of Future', type: 'MemberExpression' },
],
},
{
code: 'Future.wait([])',
errors: [
{ message: 'Invalid usage of Future', type: 'MemberExpression' },
],
},
{
code: 'Future.task()',
errors: [
{ message: 'Invalid usage of Future', type: 'MemberExpression' },
],
},
{
code: 'Future.wrap()',
errors: [
{ message: 'Invalid usage of Future', type: 'MemberExpression' },
],
},
{
code: 'Fiber(function() {})',
errors: [
{ message: 'Invalid usage of Fibers', type: 'CallExpression' },
],
},
{
code: 'Fiber.current',
errors: [
{ message: 'Invalid usage of Fibers', type: 'MemberExpression' },
],
},
{
code: 'Fiber.yield()',
errors: [
{ message: 'Invalid usage of Fibers', type: 'MemberExpression' },
],
},
],
});

0 comments on commit 2a7c96f

Please sign in to comment.