-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
no-fibers-future-usage
.
- Loading branch information
There are no files selected for viewing
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 GitHub Actions / test (14.x)
|
||
"wrap", | ||
"task", | ||
"wait", | ||
"fromPromise", | ||
]; | ||
|
||
const fibersMethods = [ | ||
Check failure on line 15 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js GitHub Actions / test (14.x)
|
||
"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 GitHub Actions / test (14.x)
|
||
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 GitHub Actions / test (14.x)
|
||
node.callee && | ||
node.callee.type === "Identifier" && | ||
Check failure on line 29 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js GitHub Actions / test (14.x)
|
||
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 GitHub Actions / test (14.x)
Check failure on line 32 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js GitHub Actions / test (14.x)
|
||
}; | ||
|
||
const isUsingFutureMethods = (node) => { | ||
const isMemberExpression = node && | ||
Check failure on line 36 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js GitHub Actions / test (14.x)
|
||
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 GitHub Actions / test (14.x)
|
||
node.object && | ||
node.object.type === "Identifier" && | ||
Check failure on line 44 in npm-packages/eslint-plugin-meteor/lib/rules/no-fibers-future-usage.js GitHub Actions / test (14.x)
|
||
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 GitHub Actions / test (14.x)
|
||
|
||
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' }, | ||
], | ||
}, | ||
], | ||
}); |