How to forbid a specific named function with ESlint
I had the same problem not so long ago so I can help you with writing your own.
So, first, let's explain some basic structures:
ESLint
has plugins, and each plugin has rules.ESLint
uses AST which is a syntax tree to find specific parts in the code. This helps ESLint find what each rule is looking for.
So, let's start by creating a plugin with a rule in it:
1. Use The ESLint Generator for Yeoman
This makes things a lot easier. Check it out here.
After you install yeoman
and the yeoman eslint generator
:
- go into the folder you want to create your project in
- run
yo eslint:plugin
to create a newESLint
plugin - after creating the plugin, run
yo eslint:rule
in the same folder
I used suni
as the plugin name, and check-as-mutable
as the rule name.
Now we have all the initial files we need to write the rule.
2. Know what you need to look for using AST Explorer
AST Explorer Can help us find what type of thing we're looking for. This is important so we can tell ESLint
what in the code we want our function to run on.
When you paste code into AST Explorer, it shows you what ESLint
is seeing.
We want to target all MemberExpression
s:
something.
asMutable
();
Inside that, we want the Identifier node
to check the function name
3. Write the plugin itself
Open lib/rules/check-as-mutable.js
and check it out. All the data you provided for Yeoman
was used to fill some fields here.
Inside the rule, you have a create
attribute. Here, we write our code. This function should return an object, with what we want our rules to run on as attributes. So, in this case, it will look like so:
create: function(context) {
return {
MemberExpression: function(node)...
};
}
While writing the rule, you should check which fields you need using the AST Explorer
.
here is the implementation:
create: function(context) {
var UNWANTED_FUNCTION_NAME = 'asMutable';
return {
MemberExpression: function reportUnwantedName(node) {
var functionName = node.property.name;
if (functionName === UNWANTED_FUNCTION_NAME) {
context.report({
node: node,
message: [
'Please don\'t use ',
UNWANTED_FUNCTION_NAME,
'. We don\'t like it!'].join('')
});
}
}
};
}
After that, you need to install the plugin in your project. To do that, upload it to GitHub, and install it using npm:
npm install --save-dev <user_name>/<repository_name>
And include the rule in your .eslintrc
file as well:
{
'plugins': ['suni'],
'rules': {
'suni/check-as-mutable': 1
}
}
Notice that I gave it the value 1
. This makes this rule show as a Warning and not as an Error
Notice that the warning highlights the Immutable itself, since that is the node
we pass to context.report
. You can tweak that to highlight the id node
instead.
Here's the plugin I created for this answer
Good luck!
You can do some very fancy things when you combine ESLint's no-restricted-syntax
rule with selectors
. In your case you should be able to achieve the linting you want without writing your own plugin. The rule would look something like:
{
rules: {
'no-restricted-syntax': [
'error',
{
message: "Please don't use asMutable. We don't like it!",
selector:
'MemberExpression > Identifier[name="asMutable"]'
}
]
}
}
Study the documentation page for selectors
; it is very flexible!
On top of @Eric Simonton's answer, since ESLint 3.5.0 we have the purpose-built no-restricted-properties:
"no-restricted-properties": [ "error", {
"object": "Immutable",
"property": "asMutable",
"message": "optional explanation to the recurring problems we've had"
}]
If anyone comes here looking for ways to block functions that aren't class methods, you can similarly use no-restricted-globals