自定义规则
你可以创建自定义规则以与 ESLint 一起使用。如果 核心规则 不涵盖你的用例,你可能想要创建自定义规则。
¥You can create custom rules to use with ESLint. You might want to create a custom rule if the core rules do not cover your use case.
以下是自定义规则的基本格式:
¥Here’s the basic format of a custom rule:
// customRule.js
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "Description of the rule",
},
fixable: "code",
schema: [] // no options
},
create: function(context) {
return {
// callback functions
};
}
};
规则结构
¥Rule Structure
规则的源文件导出具有以下属性的对象。自定义规则和核心规则都遵循这种格式。
¥The source file for a rule exports an object with the following properties. Both custom rules and core rules follow this format.
meta
:(object
)包含规则的元数据:
¥meta
: (object
) Contains metadata for the rule:
-
type
:(string
)指示规则的类型,为"problem"
、"suggestion"
或"layout"
之一:¥
type
: (string
) Indicates the type of rule, which is one of"problem"
,"suggestion"
, or"layout"
:-
"problem"
:该规则是识别将导致错误或可能导致混淆行为的代码。开发者应将此视为高度优先解决的问题。¥
"problem"
: The rule is identifying code that either will cause an error or may cause a confusing behavior. Developers should consider this a high priority to resolve. -
"suggestion"
:规则是确定可以以更好的方式完成的事情,但如果不更改代码就不会发生错误。¥
"suggestion"
: The rule is identifying something that could be done in a better way but no errors will occur if the code isn’t changed. -
"layout"
:该规则主要关注空格、分号、逗号和括号,程序的所有部分决定代码的外观而不是代码的执行方式。这些规则适用于 AST 中未指定的部分代码。¥
"layout"
: The rule cares primarily about whitespace, semicolons, commas, and parentheses, all the parts of the program that determine how the code looks rather than how it executes. These rules work on parts of the code that aren’t specified in the AST.
-
-
docs
:(object
)通常用于文档生成和工具的属性。对于核心规则是必需的,对于自定义规则是可选的。自定义规则可以根据需要在此处包含其他属性。¥
docs
: (object
) Properties often used for documentation generation and tooling. Required for core rules and optional for custom rules. Custom rules can include additional properties here as needed.-
description
:(string
)提供规则的简短描述。对于核心规则,这是在 规则索引 中使用的。¥
description
: (string
) Provides a short description of the rule. For core rules, this is used in rules index. -
recommended
:(boolean
)对于核心规则,这指定规则是否由@eslint/js
中的recommended
配置启用。¥
recommended
: (boolean
) For core rules, this specifies whether the rule is enabled by therecommended
config from@eslint/js
. -
url
:(string
)指定可以访问完整文档的 URL。代码编辑器经常使用它来提供有关高亮的规则违规的有用链接。¥
url
: (string
) Specifies the URL at which the full documentation can be accessed. Code editors often use this to provide a helpful link on highlighted rule violations.
-
-
fixable
:(string
)如果 命令行 上的--fix
选项自动修复规则报告的问题,则为"code"
或"whitespace"
。¥
fixable
: (string
) Either"code"
or"whitespace"
if the--fix
option on the command line automatically fixes problems reported by the rule.重要:对于可修复规则,
fixable
属性是强制性的。如果未指定此属性,ESLint 将在规则尝试生成修复时抛出错误。如果规则不可修复,则省略fixable
属性。¥Important: the
fixable
property is mandatory for fixable rules. If this property isn’t specified, ESLint will throw an error whenever the rule attempts to produce a fix. Omit thefixable
property if the rule is not fixable. -
hasSuggestions
:(boolean
)指定规则是否可以返回建议(如果省略,则默认为false
)。¥
hasSuggestions
: (boolean
) Specifies whether rules can return suggestions (defaults tofalse
if omitted).重要:对于提供建议的规则,
hasSuggestions
属性是强制性的。如果此属性未设置为true
,ESLint 将在规则尝试生成建议时抛出错误。如果规则不提供建议,则省略hasSuggestions
属性。¥Important: the
hasSuggestions
property is mandatory for rules that provide suggestions. If this property isn’t set totrue
, ESLint will throw an error whenever the rule attempts to produce a suggestion. Omit thehasSuggestions
property if the rule does not provide suggestions. -
schema
:(object | array | false
)指定 选项,以便 ESLint 可以防止无效的 规则配置。当规则有选项时为强制。¥
schema
: (object | array | false
) Specifies the options so ESLint can prevent invalid rule configurations. Mandatory when the rule has options. -
defaultOptions
:(array
)为规则指定 默认选项。如果存在,其配置中的任何用户提供的选项都将递归合并到它们之上。¥
defaultOptions
: (array
) Specifies default options for the rule. If present, any user-provided options in their config will be merged on top of them recursively. -
deprecated
:(boolean
)指示规则是否已被弃用。如果规则没有被弃用,你可以省略deprecated
属性。¥
deprecated
: (boolean
) Indicates whether the rule has been deprecated. You may omit thedeprecated
property if the rule has not been deprecated. -
replacedBy
:(array
)如果规则已弃用,请指定替换规则。¥
replacedBy
: (array
) In the case of a deprecated rule, specify replacement rule(s).
create()
:返回一个对象,其中包含 ESLint 在遍历 JavaScript 代码的抽象语法树(ESTree 定义的 AST)时调用到 “visit” 节点的方法:
¥create()
: Returns an object with methods that ESLint calls to “visit” nodes while traversing the abstract syntax tree (AST as defined by ESTree) of JavaScript code:
-
如果键是节点类型或 选择器,ESLint 在沿着树向下移动时会调用该访问者函数。
¥If a key is a node type or a selector, ESLint calls that visitor function while going down the tree.
-
如果键是节点类型或 选择器 加
:exit
,则 ESLint 在向上查找树时会调用该访问者函数。¥If a key is a node type or a selector plus
:exit
, ESLint calls that visitor function while going up the tree. -
如果键是事件名称,ESLint 会调用 代码路径分析 的处理函数。
¥If a key is an event name, ESLint calls that handler function for code path analysis.
规则可以使用当前节点及其周围的树来报告或修复问题。
¥A rule can use the current node and its surrounding tree to report or fix problems.
以下是 array-callback-return 规则的方法:
¥Here are methods for the array-callback-return rule:
function checkLastSegment (node) {
// report problem for function if last code path segment is reachable
}
module.exports = {
meta: { ... },
create: function(context) {
// declare the state of the rule
return {
ReturnStatement: function(node) {
// at a ReturnStatement node while going down
},
// at a function expression node while going up:
"FunctionExpression:exit": checkLastSegment,
"ArrowFunctionExpression:exit": checkLastSegment,
onCodePathStart: function (codePath, node) {
// at the start of analyzing a code path
},
onCodePathEnd: function(codePath, node) {
// at the end of analyzing a code path
}
};
}
};
上下文对象
¥The Context Object
context
对象是规则中 create
方法的唯一参数。例如:
¥The context
object is the only argument of the create
method in a rule. For example:
// customRule.js
module.exports = {
meta: { ... },
// `context` object is the argument
create(context) {
// ...
}
};
顾名思义,context
对象包含与规则上下文相关的信息。
¥As the name implies, the context
object contains information that is relevant to the context of the rule.
context
对象具有以下属性:
¥The context
object has the following properties:
-
id
:(string
)规则 ID。¥
id
: (string
) The rule ID. -
filename
:(string
)与源关联的文件名。¥
filename
: (string
) The filename associated with the source. -
physicalFilename
:(string
)对文件进行 linting 时,它会提供磁盘上文件的完整路径,而无需任何代码块信息。当检查文本时,如果未指定,它会提供传递给—stdin-filename
或<text>
的值。¥
physicalFilename
: (string
) When linting a file, it provides the full path of the file on disk without any code block information. When linting text, it provides the value passed to—stdin-filename
or<text>
if not specified. -
cwd
:(string
)cwd
选项传递给 Linter。它是应被视为当前工作目录的目录的路径。¥
cwd
: (string
) Thecwd
option passed to the Linter. It is a path to a directory that should be considered the current working directory. -
options
:(array
)此规则的 配置选项 数组。此数组不包括规则严重性(请参阅 专用部分)。¥
options
: (array
) An array of the configured options for this rule. This array does not include the rule severity (see the dedicated section). -
sourceCode
:(object
)一个SourceCode
对象,可用于处理传递给 ESLint 的源(请参阅 访问源代码)。¥
sourceCode
: (object
) ASourceCode
object that you can use to work with the source that was passed to ESLint (see Accessing the Source Code). -
settings
:(object
)从配置上看是 共享的设置。¥
settings
: (object
) The shared settings from the configuration. -
languageOptions
:(object
) 每个属性的更多详细信息 此处¥
languageOptions
: (object
) more details for each property here-
sourceType
:('script' | 'module' | 'commonjs'
)当前文件的模式。¥
sourceType
: ('script' | 'module' | 'commonjs'
) The mode for the current file. -
ecmaVersion
:(number
)用于解析当前文件的 ECMA 版本。¥
ecmaVersion
: (number
) The ECMA version used to parse the current file. -
parser
:(object
):用于解析当前文件的解析器。¥
parser
: (object
): The parser used to parse the current file. -
parserOptions
:(object
)为此文件配置的解析器选项。¥
parserOptions
: (object
) The parser options configured for this file. -
globals
:(object
)指定的全局变量。¥
globals
: (object
) The specified globals.
-
-
parserPath
:(string
,已删除,使用context.languageOptions.parser
代替。)配置中parser
的名称。¥
parserPath
: (string
, Removed Usecontext.languageOptions.parser
instead.) The name of theparser
from the configuration. -
parserOptions
:(已弃用,请使用context.languageOptions.parserOptions
代替。)为此运行配置的解析器选项(更多详细信息 此处)。¥
parserOptions
: (Deprecated Usecontext.languageOptions.parserOptions
instead.) The parser options configured for this run (more details here).
此外,context
对象具有以下方法:
¥Additionally, the context
object has the following methods:
-
getCwd()
:(已弃用:使用context.cwd
代替。)返回传递给 Linter 的cwd
选项。它是应被视为当前工作目录的目录的路径。¥
getCwd()
: (Deprecated: Usecontext.cwd
instead.) Returns thecwd
option passed to the Linter. It is a path to a directory that should be considered the current working directory. -
getFilename()
:(已弃用:使用context.filename
代替。)返回与源关联的文件名。¥
getFilename()
: (Deprecated: Usecontext.filename
instead.) Returns the filename associated with the source. -
getPhysicalFilename()
:(已弃用:使用context.physicalFilename
代替。)对文件进行 linting 时,它会返回磁盘上文件的完整路径,而不包含任何代码块信息。当检查文本时,如果未指定,它会返回传递给—stdin-filename
或<text>
的值。¥
getPhysicalFilename()
: (Deprecated: Usecontext.physicalFilename
instead.) When linting a file, it returns the full path of the file on disk without any code block information. When linting text, it returns the value passed to—stdin-filename
or<text>
if not specified. -
getSourceCode()
:(已弃用:使用context.sourceCode
代替。)返回一个SourceCode
对象,你可以使用该对象来处理传递给 ESLint 的源(请参阅 访问源代码)。¥
getSourceCode()
: (Deprecated: Usecontext.sourceCode
instead.) Returns aSourceCode
object that you can use to work with the source that was passed to ESLint (see Accessing the Source Code). -
report(descriptor)
。报告代码中的问题(参见 专用部分)。¥
report(descriptor)
. Reports a problem in the code (see the dedicated section).
注意:ESLint 的早期版本支持 context
对象上的其他方法。这些方法已在新格式中删除,不应依赖。
¥Note: Earlier versions of ESLint supported additional methods on the context
object. Those methods were removed in the new format and should not be relied upon.
报告问题
¥Reporting Problems
编写自定义规则时你将使用的主要方法是 context.report()
,它会发布警告或错误(取决于所使用的配置)。此方法接受一个参数,该参数是一个包含以下属性的对象:
¥The main method you’ll use when writing custom rules is context.report()
, which publishes a warning or error (depending on the configuration being used). This method accepts a single argument, which is an object containing the following properties:
-
messageId
:(string
)消息的 ID(参见 messageIds)(在message
上推荐)。¥
messageId
: (string
) The ID of the message (see messageIds) (recommended overmessage
). -
message
:(string
)问题消息(messageId
的替代)。¥
message
: (string
) The problem message (alternative tomessageId
). -
node
:(可选的object
)与问题相关的 AST 节点。如果存在且未指定loc
,则将节点的起始位置用作问题的位置。¥
node
: (optionalobject
) The AST node related to the problem. If present andloc
is not specified, then the starting location of the node is used as the location of the problem. -
loc
:(可选的object
)指定问题的位置。如果同时指定了loc
和node
,则使用loc
而不是node
的位置。¥
loc
: (optionalobject
) Specifies the location of the problem. If bothloc
andnode
are specified, then the location is used fromloc
instead ofnode
.-
start
:起始位置的对象。¥
start
: An object of the start location.-
line
:(number
)发生问题的从 1 开始的行号。¥
line
: (number
) The 1-based line number at which the problem occurred. -
column
:(number
)发生问题的从 0 开始的列号。¥
column
: (number
) The 0-based column number at which the problem occurred.
-
-
end
:结束位置的对象。¥
end
: An object of the end location.-
line
:(number
)发生问题的从 1 开始的行号。¥
line
: (number
) The 1-based line number at which the problem occurred. -
column
:(number
)发生问题的从 0 开始的列号。¥
column
: (number
) The 0-based column number at which the problem occurred.
-
-
-
data
:(可选的object
)message
的 占位符 数据。¥
data
: (optionalobject
) Placeholder data formessage
. -
fix(fixer)
:(可选的function
)应用 fix 来解决问题。¥
fix(fixer)
: (optionalfunction
) Applies a fix to resolve the problem.
请注意,至少需要 node
或 loc
之一。
¥Note that at least one of node
or loc
is required.
最简单的示例是仅使用 node
和 message
:
¥The simplest example is to use just node
and message
:
context.report({
node: node,
message: "Unexpected identifier"
});
该节点包含找出违规文本的行号和列号以及代表该节点的源文本所需的所有信息。
¥The node contains all the information necessary to figure out the line and column number of the offending text as well as the source text representing the node.
使用消息占位符
¥Using Message Placeholders
你还可以在消息中使用占位符并提供 data
:
¥You can also use placeholders in the message and provide data
:
context.report({ node: node, message: “Unexpected identifier: {{ identifier }}”, data: { identifier: node.name } });
请注意,前导和尾随空格在消息参数中是可选的。
¥Note that leading and trailing whitespace is optional in message parameters.
该节点包含找出违规文本的行号和列号以及代表该节点的源文本所需的所有信息。
¥The node contains all the information necessary to figure out the line and column number of the offending text as well as the source text representing the node.
messageId
messageId
是在 context.report()
调用中报告消息的推荐方法,因为它具有以下优点:
¥messageId
s are the recommended approach to reporting messages in context.report()
calls because of the following benefits:
-
规则违规消息可以存储在中央
meta.messages
对象中,以便于管理¥Rule violation messages can be stored in a central
meta.messages
object for convenient management -
规则违规消息不需要在规则文件和规则测试文件中重复
¥Rule violation messages do not need to be repeated in both the rule file and rule test file
-
因此,更改违规消息的障碍较低,鼓励更频繁的贡献来改进和优化它们,以获得最大的清晰度和实用性
¥As a result, the barrier for changing rule violation messages is lower, encouraging more frequent contributions to improve and optimize them for the greatest clarity and usefulness
规则文件:
¥Rule file:
// avoid-name.js
module.exports = { meta: { messages: { avoidName: “Avoid using variables named ‘{{ name }}’” } }, create(context) { return { Identifier(node) { if (node.name === “foo”) { context.report({ node, messageId: “avoidName”, data: { name: “foo”, } }); } } }; } };
在要 lint 的文件中:
¥In the file to lint:
// someFile.js
var foo = 2;
// ^ error: Avoid using variables named 'foo'
在你的测试中:
¥In your tests:
// avoid-name.test.js
var rule = require("../../../lib/rules/avoid-name");
var RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
ruleTester.run("avoid-name", rule, {
valid: ["bar", "baz"],
invalid: [
{
code: "foo",
errors: [
{
messageId: "avoidName"
}
]
}
]
});
应用修复
¥Applying Fixes
如果你希望 ESLint 尝试修复你报告的问题,你可以通过在使用 context.report()
时指定 fix
函数来实现。fix
函数接收一个参数,一个 fixer
对象,你可以使用它来应用修复。例如:
¥If you’d like ESLint to attempt to fix the problem you’re reporting, you can do so by specifying the fix
function when using context.report()
. The fix
function receives a single argument, a fixer
object, that you can use to apply a fix. For example:
context.report({
node: node,
message: "Missing semicolon",
fix(fixer) {
return fixer.insertTextAfter(node, ";");
}
});
在这里,fix()
函数用于在节点后插入一个分号。请注意,修复不会立即应用,如果与其他修复存在冲突,则可能根本不会应用。应用修复后,ESLint 将在修复的代码上再次运行所有启用的规则,可能会应用更多修复。此过程将重复最多 10 次,或直到找不到更多可修复的问题。之后,将照常报告任何剩余问题。
¥Here, the fix()
function is used to insert a semicolon after the node. Note that a fix is not immediately applied, and may not be applied at all if there are conflicts with other fixes. After applying fixes, ESLint will run all the enabled rules again on the fixed code, potentially applying more fixes. This process will repeat up to 10 times, or until no more fixable problems are found. Afterward, any remaining problems will be reported as usual.
重要:meta.fixable
属性对于可修复规则是必需的。如果实现 fix
功能的规则没有 export meta.fixable
属性,ESLint 将抛出错误。
¥Important: The meta.fixable
property is mandatory for fixable rules. ESLint will throw an error if a rule that implements fix
functions does not export the meta.fixable
property.
fixer
对象具有以下方法:
¥The fixer
object has the following methods:
-
insertTextAfter(nodeOrToken, text)
:在给定的节点或标记之后插入文本。¥
insertTextAfter(nodeOrToken, text)
: Insert text after the given node or token. -
insertTextAfterRange(range, text)
:在给定范围后插入文本。¥
insertTextAfterRange(range, text)
: Insert text after the given range. -
insertTextBefore(nodeOrToken, text)
:在给定节点或标记之前插入文本。¥
insertTextBefore(nodeOrToken, text)
: Insert text before the given node or token. -
insertTextBeforeRange(range, text)
:在给定范围之前插入文本。¥
insertTextBeforeRange(range, text)
: Insert text before the given range. -
remove(nodeOrToken)
:删除给定的节点或令牌。¥
remove(nodeOrToken)
: Remove the given node or token. -
removeRange(range)
:删除给定范围内的文本。¥
removeRange(range)
: Remove text in the given range. -
replaceText(nodeOrToken, text)
:替换给定节点或标记中的文本。¥
replaceText(nodeOrToken, text)
: Replace the text in the given node or token. -
replaceTextRange(range, text)
:替换给定范围内的文本。¥
replaceTextRange(range, text)
: Replace the text in the given range.
range
是一个包含源代码内部字符索引的两项数组。第一项是范围的开始(包括),第二项是范围的结束(不包括)。每个节点和令牌都有一个 range
属性来标识它们所代表的源代码范围。
¥A range
is a two-item array containing character indices inside the source code. The first item is the start of the range (inclusive) and the second item is the end of the range (exclusive). Every node and token has a range
property to identify the source code range they represent.
上述方法返回一个 fixing
对象。fix()
函数可以返回以下值:
¥The above methods return a fixing
object.
The fix()
function can return the following values:
-
一个
fixing
对象。¥A
fixing
object. -
包含
fixing
个对象的数组。¥An array which includes
fixing
objects. -
枚举
fixing
个对象的可迭代对象。特别是,fix()
函数可以是一个生成器。¥An iterable object which enumerates
fixing
objects. Especially, thefix()
function can be a generator.
如果你创建一个返回多个 fixing
对象的 fix()
函数,则这些 fixing
对象不得重叠。
¥If you make a fix()
function which returns multiple fixing
objects, those fixing
objects must not overlap.
修复的最佳实践:
¥Best practices for fixes:
-
避免任何可能改变代码运行时行为并导致其停止工作的修复。
¥Avoid any fixes that could change the runtime behavior of code and cause it to stop working.
-
使修复尽可能小。过大的修复可能会与其他修复发生冲突,并阻止应用它们。
¥Make fixes as small as possible. Fixes that are unnecessarily large could conflict with other fixes, and prevent them from being applied.
-
每条消息只修复一次。这是强制执行的,因为你必须从
fix()
返回修复程序操作的结果。¥Only make one fix per message. This is enforced because you must return the result of the fixer operation from
fix()
. -
由于在应用第一轮修复后所有规则都会再次运行,因此规则没有必要检查修复的代码风格是否会导致另一条规则报告错误。
¥Since all rules are run again after the initial round of fixes is applied, it’s not necessary for a rule to check whether the code style of a fix will cause errors to be reported by another rule.
-
例如,假设修复者想用引号将对象键括起来,但不确定用户更喜欢单引号还是双引号。
¥For example, suppose a fixer would like to surround an object key with quotes, but it’s not sure whether the user would prefer single or double quotes.
({ foo : 1 }) // should get fixed to either ({ 'foo': 1 }) // or ({ "foo": 1 })
-
这个固定器可以任意选择一个引号类型。如果猜错了,结果代码会自动上报,并被
quotes
规则修复。¥This fixer can just select a quote type arbitrarily. If it guesses wrong, the resulting code will be automatically reported and fixed by the
quotes
rule.
-
注意:使修复尽可能小是最佳做法,但在某些情况下,为了有意防止其他规则在同一遍中在周围范围内进行修复,扩展修复范围可能是正确的。例如,如果替换文本声明了一个新变量,则可以防止变量范围内的其他更改很有用,因为它们可能会导致名称冲突。
¥Note: Making fixes as small as possible is a best practice, but in some cases it may be correct to extend the range of the fix in order to intentionally prevent other rules from making fixes in a surrounding range in the same pass. For instance, if replacement text declares a new variable, it can be useful to prevent other changes in the scope of the variable as they might cause name collisions.
以下示例替换了 node
,并确保在同一遍中不会在 node.parent
的范围内应用其他修复:
¥The following example replaces node
and also ensures that no other fixes will be applied in the range of node.parent
in the same pass:
context.report({
node,
message,
*fix(fixer) {
yield fixer.replaceText(node, replacementText);
// extend range of the fix to the range of `node.parent`
yield fixer.insertTextBefore(node.parent, "");
yield fixer.insertTextAfter(node.parent, "");
}
});
冲突修复
¥Conflicting Fixes
冲突修复是对源代码的同一部分应用不同更改的修复。无法指定应用了哪些冲突修复程序。
¥Conflicting fixes are fixes that apply different changes to the same part of the source code. There is no way to specify which of the conflicting fixes is applied.
例如,如果有两个修复要修改字符 0 到 5,则只应用一个。
¥For example, if two fixes want to modify characters 0 through 5, only one is applied.
提供建议
¥Providing Suggestions
在某些情况下,修复不适合自动应用,例如,如果修复可能会更改功能,或者根据实现意图有多种有效方法来修复规则(请参阅上面列出的 应用修复 的最佳实践)。在这些情况下,context.report()
上有一个替代的 suggest
选项,它允许其他工具(例如编辑器)向用户公开辅助程序以手动应用建议。
¥In some cases fixes aren’t appropriate to be automatically applied, for example, if a fix potentially changes functionality or if there are multiple valid ways to fix a rule depending on the implementation intent (see the best practices for applying fixes listed above). In these cases, there is an alternative suggest
option on context.report()
that allows other tools, such as editors, to expose helpers for users to manually apply a suggestion.
要提供建议,请在带有建议对象数组的报告参数中使用 suggest
键。建议对象表示可以应用的个人建议,需要一个 desc
键字符串来描述应用建议会做什么或 messageId
键(参见 below),以及一个 fix
键,它是一个定义建议结果的函数。此 fix
函数遵循与常规修复相同的 API(在上面的 应用修复 中描述)。
¥To provide suggestions, use the suggest
key in the report argument with an array of suggestion objects. The suggestion objects represent individual suggestions that could be applied and require either a desc
key string that describes what applying the suggestion would do or a messageId
key (see below), and a fix
key that is a function defining the suggestion result. This fix
function follows the same API as regular fixes (described above in applying fixes).
context.report({
node: node,
message: “Unnecessary escape character: \{{character}}.”,
data: { character },
suggest: [
{
desc: “Remove the \\
. This maintains the current functionality.”,
fix: function(fixer) {
return fixer.removeRange(range);
}
},
{
desc: “Replace the \\
with \\\\
to include the actual backslash character.”,
fix: function(fixer) {
return fixer.insertTextBeforeRange(range, “\”);
}
}
]
});
重要:meta.hasSuggestions
属性对于提供建议的规则是必需的。如果规则试图产生一个建议但没有 export 这个属性,ESLint 将抛出一个错误。
¥Important: The meta.hasSuggestions
property is mandatory for rules that provide suggestions. ESLint will throw an error if a rule attempts to produce a suggestion but does not export this property.
注意:建议作为独立更改应用,不会触发多通道修复。每个建议都应该集中在代码的单一变化上,而不应该试图符合用户定义的样式。例如,如果一个建议是在代码库中添加一个新语句,它不应该尝试匹配正确的缩进或符合用户对分号存在/不存在的偏好。当用户触发它时,所有这些事情都可以通过多通道自动修复来纠正。
¥Note: Suggestions are applied as stand-alone changes, without triggering multipass fixes. Each suggestion should focus on a singular change in the code and should not try to conform to user-defined styles. For example, if a suggestion is adding a new statement into the codebase, it should not try to match correct indentation or conform to user preferences on the presence/absence of semicolons. All of those things can be corrected by multipass autofix when the user triggers it.
建议的最佳实践:
¥Best practices for suggestions:
-
不要尝试做太多,也不要建议可能会引入大量重大更改的大型重构。
¥Don’t try to do too much and suggest large refactors that could introduce a lot of breaking changes.
-
如上所述,不要试图符合用户定义的样式。
¥As noted above, don’t try to conform to user-defined styles.
建议旨在提供修复。如果建议的 fix
函数返回 null
或空数组/序列,ESLint 会自动从 linting 输出中删除整个建议。
¥Suggestions are intended to provide fixes. ESLint will automatically remove the whole suggestion from the linting output if the suggestion’s fix
function returned null
or an empty array/sequence.
建议 messageId
¥Suggestion messageId
s
可以使用 messageId
代替建议,而不是使用 desc
键。对于总体误差,其工作方式与 messageId
相同(参见 messageIds)。以下是如何在规则中使用建议 messageId
的示例:
¥Instead of using a desc
key for suggestions a messageId
can be used instead. This works the same way as messageId
s for the overall error (see messageIds). Here is an example of how to use a suggestion messageId
in a rule:
module.exports = {
meta: {
messages: {
unnecessaryEscape: “Unnecessary escape character: \{{character}}.”,
removeEscape: “Remove the \\
. This maintains the current functionality.”,
escapeBackslash: “Replace the \\
with \\\\
to include the actual backslash character.”
},
hasSuggestions: true
},
create: function(context) {
// …
context.report({
node: node,
messageId: ‘unnecessaryEscape’,
data: { character },
suggest: [
{
messageId: “removeEscape”, // suggestion messageId
fix: function(fixer) {
return fixer.removeRange(range);
}
},
{
messageId: “escapeBackslash”, // suggestion messageId
fix: function(fixer) {
return fixer.insertTextBeforeRange(range, “\”);
}
}
]
});
}
};
建议消息中的占位符
¥Placeholders in Suggestion Messages
你还可以在建议消息中使用占位符。这与整体错误的占位符的工作方式相同(请参阅 使用消息占位符)。
¥You can also use placeholders in the suggestion message. This works the same way as placeholders for the overall error (see using message placeholders).
请注意,你必须在建议的对象上提供 data
。建议消息不能使用总体错误的 data
中的属性。
¥Please note that you have to provide data
on the suggestion’s object. Suggestion messages cannot use properties from the overall error’s data
.
module.exports = {
meta: {
messages: {
unnecessaryEscape: “Unnecessary escape character: \{{character}}.”,
removeEscape: “Remove \\
before {{character}}.”,
},
hasSuggestions: true
},
create: function(context) {
// …
context.report({
node: node,
messageId: “unnecessaryEscape”,
data: { character }, // data for the unnecessaryEscape overall message
suggest: [
{
messageId: “removeEscape”,
data: { character }, // data for the removeEscape suggestion message
fix: function(fixer) {
return fixer.removeRange(range);
}
}
]
});
}
};
访问传递给规则的选项
¥Accessing Options Passed to a Rule
某些规则需要选项才能正常运行。这些选项出现在配置中(.eslintrc
、命令行接口或注释)。例如:
¥Some rules require options in order to function correctly. These options appear in configuration (.eslintrc
, command line interface, or comments). For example:
{
"quotes": ["error", "double"]
}
本例中的 quotes
规则有一个选项,"double"
(error
是错误级别)。你可以使用 context.options
检索规则的选项,context.options
是一个包含规则的每个配置选项的数组。在这种情况下,context.options[0]
将包含 "double"
:
¥The quotes
rule in this example has one option, "double"
(the error
is the error level). You can retrieve the options for a rule by using context.options
, which is an array containing every configured option for the rule. In this case, context.options[0]
would contain "double"
:
module.exports = {
meta: {
schema: [
{
enum: ["single", "double", "backtick"]
}
]
},
create: function(context) {
var isDouble = (context.options[0] === "double");
// ...
}
};
由于 context.options
只是一个数组,你可以使用它来确定已传递的选项数量以及检索实际选项本身。请记住,错误级别不是 context.options
的一部分,因为无法从规则内部获知或修改错误级别。
¥Since context.options
is just an array, you can use it to determine how many options have been passed as well as retrieving the actual options themselves. Keep in mind that the error level is not part of context.options
, as the error level cannot be known or modified from inside a rule.
使用选项时,请确保你的规则具有一些逻辑默认值,以防未提供选项。
¥When using options, make sure that your rule has some logical defaults in case the options are not provided.
带有选项的规则必须指定 schema。
¥Rules with options must specify a schema.
访问源代码
¥Accessing the Source Code
SourceCode
对象是获取有关正在检查的源代码的更多信息的主要对象。你可以随时使用 context.sourceCode
属性检索 SourceCode
对象:
¥The SourceCode
object is the main object for getting more information about the source code being linted. You can retrieve the SourceCode
object at any time by using the context.sourceCode
property:
module.exports = {
create: function(context) {
var sourceCode = context.sourceCode;
// ...
}
};
已弃用:context.getSourceCode()
方法已弃用;确保改用 context.sourceCode
属性。
¥Deprecated: The context.getSourceCode()
method is deprecated; make sure to use context.sourceCode
property instead.
拥有 SourceCode
的实例后,你可以在其上使用以下方法来处理代码:
¥Once you have an instance of SourceCode
, you can use the following methods on it to work with the code:
-
getText(node)
:返回给定节点的源代码。省略node
以获得完整的源代码(参见 专用部分)。¥
getText(node)
: Returns the source code for the given node. Omitnode
to get the whole source (see the dedicated section). -
getAllComments()
:返回源中所有注释的数组(参见 专用部分)。¥
getAllComments()
: Returns an array of all comments in the source (see the dedicated section). -
getCommentsBefore(nodeOrToken)
:返回直接出现在给定节点或标记之前的注释标记数组(请参阅 专用部分)。¥
getCommentsBefore(nodeOrToken)
: Returns an array of comment tokens that occur directly before the given node or token (see the dedicated section). -
getCommentsAfter(nodeOrToken)
:返回在给定节点或标记之后直接出现的注释标记数组(请参阅 专用部分)。¥
getCommentsAfter(nodeOrToken)
: Returns an array of comment tokens that occur directly after the given node or token (see the dedicated section). -
getCommentsInside(node)
:返回给定节点内所有注释标记的数组(请参阅 专用部分)。¥
getCommentsInside(node)
: Returns an array of all comment tokens inside a given node (see the dedicated section). -
isSpaceBetween(nodeOrToken, nodeOrToken)
:如果两个标记之间有空白字符,或者如果给定一个节点,第一个节点的最后一个标记和第二个节点的第一个标记,则返回 true。¥
isSpaceBetween(nodeOrToken, nodeOrToken)
: Returns true if there is a whitespace character between the two tokens or, if given a node, the last token of the first node and the first token of the second node. -
getFirstToken(node, skipOptions)
:返回表示给定节点的第一个标记。¥
getFirstToken(node, skipOptions)
: Returns the first token representing the given node. -
getFirstTokens(node, countOptions)
:返回代表给定节点的前count
个标记。¥
getFirstTokens(node, countOptions)
: Returns the firstcount
tokens representing the given node. -
getLastToken(node, skipOptions)
:返回表示给定节点的最后一个标记。¥
getLastToken(node, skipOptions)
: Returns the last token representing the given node. -
getLastTokens(node, countOptions)
:返回表示给定节点的最后count
个令牌。¥
getLastTokens(node, countOptions)
: Returns the lastcount
tokens representing the given node. -
getTokenAfter(nodeOrToken, skipOptions)
:返回给定节点或标记之后的第一个标记。¥
getTokenAfter(nodeOrToken, skipOptions)
: Returns the first token after the given node or token. -
getTokensAfter(nodeOrToken, countOptions)
:返回给定节点或标记后的count
个标记。¥
getTokensAfter(nodeOrToken, countOptions)
: Returnscount
tokens after the given node or token. -
getTokenBefore(nodeOrToken, skipOptions)
:返回给定节点或标记之前的第一个标记。¥
getTokenBefore(nodeOrToken, skipOptions)
: Returns the first token before the given node or token. -
getTokensBefore(nodeOrToken, countOptions)
:返回给定节点或标记之前的count
个标记。¥
getTokensBefore(nodeOrToken, countOptions)
: Returnscount
tokens before the given node or token. -
getFirstTokenBetween(nodeOrToken1, nodeOrToken2, skipOptions)
:返回两个节点或标记之间的第一个标记。¥
getFirstTokenBetween(nodeOrToken1, nodeOrToken2, skipOptions)
: Returns the first token between two nodes or tokens. -
getFirstTokensBetween(nodeOrToken1, nodeOrToken2, countOptions)
:返回两个节点或令牌之间的第一个count
令牌。¥
getFirstTokensBetween(nodeOrToken1, nodeOrToken2, countOptions)
: Returns the firstcount
tokens between two nodes or tokens. -
getLastTokenBetween(nodeOrToken1, nodeOrToken2, skipOptions)
:返回两个节点或令牌之间的最后一个令牌。¥
getLastTokenBetween(nodeOrToken1, nodeOrToken2, skipOptions)
: Returns the last token between two nodes or tokens. -
getLastTokensBetween(nodeOrToken1, nodeOrToken2, countOptions)
:返回两个节点或令牌之间的最后count
个令牌。¥
getLastTokensBetween(nodeOrToken1, nodeOrToken2, countOptions)
: Returns the lastcount
tokens between two nodes or tokens. -
getTokens(node)
:返回给定节点的所有标记。¥
getTokens(node)
: Returns all tokens for the given node. -
getTokensBetween(nodeOrToken1, nodeOrToken2)
:返回两个节点之间的所有令牌。¥
getTokensBetween(nodeOrToken1, nodeOrToken2)
: Returns all tokens between two nodes. -
getTokenByRangeStart(index, rangeOptions)
:返回其范围从源中的给定索引开始的标记。¥
getTokenByRangeStart(index, rangeOptions)
: Returns the token whose range starts at the given index in the source. -
getNodeByRangeIndex(index)
:返回包含给定源索引的 AST 中最深的节点。¥
getNodeByRangeIndex(index)
: Returns the deepest node in the AST containing the given source index. -
getLocFromIndex(index)
:返回具有line
和column
属性的对象,对应于给定源索引的位置。line
从 1 开始,column
从 0 开始。¥
getLocFromIndex(index)
: Returns an object withline
andcolumn
properties, corresponding to the location of the given source index.line
is 1-based andcolumn
is 0-based. -
getIndexFromLoc(loc)
:返回源代码中给定位置的索引,其中loc
是具有基于 1 的line
键和基于 0 的column
键的对象。¥
getIndexFromLoc(loc)
: Returns the index of a given location in the source code, whereloc
is an object with a 1-basedline
key and a 0-basedcolumn
key. -
commentsExistBetween(nodeOrToken1, nodeOrToken2)
:如果两个节点之间存在注释,则返回true
。¥
commentsExistBetween(nodeOrToken1, nodeOrToken2)
: Returnstrue
if comments exist between two nodes. -
getAncestors(node)
:返回给定节点的祖级数组,从 AST 的根开始,一直到给定节点的直接父节点。该数组不包括给定节点本身。¥
getAncestors(node)
: Returns an array of the ancestors of the given node, starting at the root of the AST and continuing through the direct parent of the given node. This array does not include the given node itself. -
getDeclaredVariables(node)
:返回给定节点声明的 variables 列表。此信息可用于跟踪对变量的引用。¥
getDeclaredVariables(node)
: Returns a list of variables declared by the given node. This information can be used to track references to variables.-
如果节点是
VariableDeclaration
,则返回声明中声明的所有变量。¥If the node is a
VariableDeclaration
, all variables declared in the declaration are returned. -
如果节点是
VariableDeclarator
,则返回声明符中声明的所有变量。¥If the node is a
VariableDeclarator
, all variables declared in the declarator are returned. -
如果节点是
FunctionDeclaration
或FunctionExpression
,则除了函数参数的变量外,还返回函数名称的变量。¥If the node is a
FunctionDeclaration
orFunctionExpression
, the variable for the function name is returned, in addition to variables for the function parameters. -
如果节点是
ArrowFunctionExpression
,则返回参数的变量。¥If the node is an
ArrowFunctionExpression
, variables for the parameters are returned. -
如果节点是
ClassDeclaration
或ClassExpression
,则返回类名的变量。¥If the node is a
ClassDeclaration
or aClassExpression
, the variable for the class name is returned. -
如果节点是
CatchClause
,则返回异常变量。¥If the node is a
CatchClause
, the variable for the exception is returned. -
如果节点是
ImportDeclaration
,则返回其所有说明符的变量。¥If the node is an
ImportDeclaration
, variables for all of its specifiers are returned. -
如果节点是
ImportSpecifier
、ImportDefaultSpecifier
或ImportNamespaceSpecifier
,则返回声明的变量。¥If the node is an
ImportSpecifier
,ImportDefaultSpecifier
, orImportNamespaceSpecifier
, the declared variable is returned. -
否则,如果节点没有声明任何变量,则返回一个空数组。
¥Otherwise, if the node does not declare any variables, an empty array is returned.
-
-
getScope(node)
:返回给定节点的 scope。此信息可用于跟踪对变量的引用。¥
getScope(node)
: Returns the scope of the given node. This information can be used to track references to variables. -
markVariableAsUsed(name, refNode)
:将给定引用节点指示的范围内具有给定名称的变量标记为已使用。这会影响 no-unused-vars 规则。如果找到具有给定名称的变量并将其标记为已使用,则返回true
,否则返回false
。¥
markVariableAsUsed(name, refNode)
: Marks a variable with the given name in a scope indicated by the given reference node as used. This affects the no-unused-vars rule. Returnstrue
if a variable with the given name was found and marked as used, otherwisefalse
.
skipOptions
是一个具有 3 个属性的对象;skip
、includeComments
和 filter
。默认为 {skip: 0, includeComments: false, filter: null}
。
¥skipOptions
is an object which has 3 properties; skip
, includeComments
, and filter
. Default is {skip: 0, includeComments: false, filter: null}
.
-
skip
:(number
)正整数,跳过标记的数量。如果同时给出filter
选项,则不会将已过滤的标记计为已跳过。¥
skip
: (number
) Positive integer, the number of skipping tokens. Iffilter
option is given at the same time, it doesn’t count filtered tokens as skipped. -
includeComments
:(boolean
)将注释标记包含到结果中的标志。¥
includeComments
: (boolean
) The flag to include comment tokens into the result. -
filter(token)
:获取标记作为第一个参数的函数。如果函数返回false
,则结果不包括标记。¥
filter(token)
: Function which gets a token as the first argument. If the function returnsfalse
then the result excludes the token.
countOptions
是一个具有 3 个属性的对象;count
、includeComments
和 filter
。默认为 {count: 0, includeComments: false, filter: null}
。
¥countOptions
is an object which has 3 properties; count
, includeComments
, and filter
. Default is {count: 0, includeComments: false, filter: null}
.
-
count
:(number
)正整数,返回 token 的最大数量。¥
count
: (number
) Positive integer, the maximum number of returning tokens. -
includeComments
:(boolean
)将注释标记包含到结果中的标志。¥
includeComments
: (boolean
) The flag to include comment tokens into the result. -
filter(token)
:获取标记作为第一个参数的函数,如果函数返回false
,则结果不包括标记。¥
filter(token)
: Function which gets a token as the first argument, if the function returnsfalse
then the result excludes the token.
rangeOptions
是具有 1 个属性 includeComments
的对象。默认为 {includeComments: false}
。
¥rangeOptions
is an object that has 1 property, includeComments
. Default is {includeComments: false}
.
-
includeComments
:(boolean
)将注释标记包含到结果中的标志。¥
includeComments
: (boolean
) The flag to include comment tokens into the result.
你还可以访问一些属性:
¥There are also some properties you can access:
-
hasBOM
:(boolean
)该标志指示源代码是否具有 Unicode BOM。¥
hasBOM
: (boolean
) The flag to indicate whether the source code has Unicode BOM. -
text
:(string
)正在检查的代码的全文。Unicode BOM 已从本文中删除。¥
text
: (string
) The full text of the code being linted. Unicode BOM has been stripped from this text. -
ast
:(object
)正在检查的代码的 AST 的Program
节点。¥
ast
: (object
)Program
node of the AST for the code being linted. -
scopeManager
:代码的 ScopeManager 对象。¥
scopeManager
: ScopeManager object of the code. -
visitorKeys
:(object
)遍历此 AST 的访问者键。¥
visitorKeys
: (object
) Visitor keys to traverse this AST. -
parserServices
:(object
)包含解析器提供的规则服务。默认解析器不提供任何服务。但是,如果规则旨在与自定义解析器一起使用,则它可以使用parserServices
来访问该解析器提供的任何内容。(例如,TypeScript 解析器可以提供获取给定节点的计算类型的能力。)¥
parserServices
: (object
) Contains parser-provided services for rules. The default parser does not provide any services. However, if a rule is intended to be used with a custom parser, it could useparserServices
to access anything provided by that parser. (For example, a TypeScript parser could provide the ability to get the computed type of a given node.) -
lines
:(array
)行数组,根据规范的换行符定义进行分割。¥
lines
: (array
) Array of lines, split according to the specification’s definition of line breaks.
每当你需要获取有关被检查代码的更多信息时,你都应该使用 SourceCode
对象。
¥You should use a SourceCode
object whenever you need to get more information about the code being linted.
访问源文本
¥Accessing the Source Text
如果你的规则需要获取实际的 JavaScript 源代码才能使用,请使用 sourceCode.getText()
方法。此方法的工作原理如下:
¥If your rule needs to get the actual JavaScript source to work with, then use the sourceCode.getText()
method. This method works as follows:
// get all source
var source = sourceCode.getText();
// get source for just this AST node
var nodeSource = sourceCode.getText(node);
// get source for AST node plus previous two characters
var nodeSourceWithPrev = sourceCode.getText(node, 2);
// get source for AST node plus following two characters
var nodeSourceWithFollowing = sourceCode.getText(node, 0, 2);
这样,当 AST 未提供适当数据(例如逗号、分号、括号等的位置)时,你可以在 JavaScript 文本本身中查找模式。
¥In this way, you can look for patterns in the JavaScript text itself when the AST isn’t providing the appropriate data (such as the location of commas, semicolons, parentheses, etc.).
访问注释
¥Accessing Comments
虽然注释在技术上不是 AST 的一部分,但 ESLint 提供了 sourceCode.getAllComments()
、sourceCode.getCommentsBefore()
、sourceCode.getCommentsAfter()
和 sourceCode.getCommentsInside()
来访问它们。
¥While comments are not technically part of the AST, ESLint provides the sourceCode.getAllComments()
, sourceCode.getCommentsBefore()
, sourceCode.getCommentsAfter()
, and sourceCode.getCommentsInside()
to access them.
sourceCode.getCommentsBefore()
、sourceCode.getCommentsAfter()
和 sourceCode.getCommentsInside()
对于需要检查与给定节点或令牌相关的注释的规则很有用。
¥sourceCode.getCommentsBefore()
, sourceCode.getCommentsAfter()
, and sourceCode.getCommentsInside()
are useful for rules that need to check comments in relation to a given node or token.
请记住,这些方法的结果是按需计算的。
¥Keep in mind that the results of these methods are calculated on demand.
你还可以使用 includeComments
选项通过 sourceCode
的许多方法访问注释。
¥You can also access comments through many of sourceCode
’s methods using the includeComments
option.
选项模式
¥Options Schemas
带有选项的规则必须指定 meta.schema
属性,它是规则选项的 JSON 结构 格式描述,ESLint 将使用它来验证配置选项并防止无效或意外的输入,然后再将其传递给 context.options
中的规则。
¥Rules with options must specify a meta.schema
property, which is a JSON Schema format description of a rule’s options which will be used by ESLint to validate configuration options and prevent invalid or unexpected inputs before they are passed to the rule in context.options
.
如果你的规则有选项,强烈建议你指定选项验证的架构。但是,可以通过设置 schema: false
来选择退出选项验证,但不鼓励这样做,因为它会增加出现错误和错误的机会。
¥If your rule has options, it is strongly recommended that you specify a schema for options validation. However, it is possible to opt-out of options validation by setting schema: false
, but doing so is discouraged as it increases the chance of bugs and mistakes.
对于未指定 meta.schema
属性的规则,ESLint 在传递任何选项时都会引发错误。如果你的规则没有选项,请不要设置 schema: false
,而只需省略 schema 属性或使用 schema: []
,这两者都会阻止传递任何选项。
¥For rules that don’t specify a meta.schema
property, ESLint throws errors when any options are passed. If your rule doesn’t have options, do not set schema: false
, but simply omit the schema property or use schema: []
, both of which prevent any options from being passed.
验证规则的配置时,有五个步骤:
¥When validating a rule’s config, there are five steps:
-
如果规则配置不是数组,则将值封装到数组中(例如
"off"
变为["off"]
);如果规则配置是一个数组,则直接使用它。¥If the rule config is not an array, then the value is wrapped into an array (e.g.
"off"
becomes["off"]
); if the rule config is an array then it is used directly. -
ESLint 将规则配置数组的第一个元素验证为严重性(
"off"
、"warn"
、"error"
、0
、1
、2
)¥ESLint validates the first element of the rule config array as a severity (
"off"
,"warn"
,"error"
,0
,1
,2
) -
如果严重性为
off
或0
,则禁用规则并停止验证,忽略规则配置数组的任何其他元素。¥If the severity is
off
or0
, then the rule is disabled and validation stops, ignoring any other elements of the rule config array. -
如果启用规则,则严重性之后的数组中的任何元素都会复制到
context.options
数组中(例如["warn", "never", { someOption: 5 }]
的配置会导致context.options = ["never", { someOption: 5 }]
)¥If the rule is enabled, then any elements of the array after the severity are copied into the
context.options
array (e.g. a config of["warn", "never", { someOption: 5 }]
results incontext.options = ["never", { someOption: 5 }]
) -
规则的架构验证在
context.options
数组上运行。¥The rule’s schema validation is run on the
context.options
array.
注意:这意味着规则架构无法验证严重性。规则架构仅验证规则配置中严重性之后的数组元素。规则无法知道其配置的严重性。
¥Note: this means that the rule schema cannot validate the severity. The rule schema only validates the array elements after the severity in a rule config. There is no way for a rule to know what severity it is configured at.
规则的 schema
有两种格式:
¥There are two formats for a rule’s schema
:
-
JSON Schema 对象的数组
¥An array of JSON Schema objects
-
将根据
context.options
数组中的相同位置检查每个元素。¥Each element will be checked against the same position in the
context.options
array. -
如果
context.options
数组的元素少于模式,则忽略不匹配的模式¥If the
context.options
array has fewer elements than there are schemas, then the unmatched schemas are ignored -
如果
context.options
数组的元素多于模式,则验证失败¥If the
context.options
array has more elements than there are schemas, then the validation fails -
使用这种格式有两个重要的后果:
¥There are two important consequences to using this format:
-
用户不向你的规则提供任何选项始终有效(超出严重性)
¥It is always valid for a user to provide no options to your rule (beyond severity)
-
如果你指定一个空数组,那么用户为你的规则提供任何选项始终是一个错误(超出严重性)
¥If you specify an empty array, then it is always an error for a user to provide any options to your rule (beyond severity)
-
-
-
将验证
context.options
数组的完整 JSON 架构对象¥A full JSON Schema object that will validate the
context.options
array-
即使你的规则只接受一个选项,架构也应该假设一组选项进行验证。
¥The schema should assume an array of options to validate even if your rule only accepts one option.
-
该模式可以任意复杂,因此你可以通过
oneOf
、anyOf
等验证完全不同的潜在选项集。¥The schema can be arbitrarily complex, so you can validate completely different sets of potential options via
oneOf
,anyOf
etc. -
支持的 JSON Schemas 版本是 Draft-04,因此一些较新的功能(例如
if
或$data
)不可用。¥The supported version of JSON Schemas is Draft-04, so some newer features such as
if
or$data
are unavailable.-
目前,由于生态系统兼容性问题,明确计划不更新超出此级别的架构支持。请参阅 此提交 了解更多背景信息。
¥At present, it is explicitly planned to not update schema support beyond this level due to ecosystem compatibility concerns. See this comment for further context.
-
-
例如,yoda
规则接受 "always"
或 "never"
的主模式参数,以及带有可选属性 exceptRange
的额外选项对象:
¥For example, the yoda
rule accepts a primary mode argument of "always"
or "never"
, as well as an extra options object with an optional property exceptRange
:
// Valid configuration:
// "yoda": "warn"
// "yoda": ["error"]
// "yoda": ["error", "always"]
// "yoda": ["error", "never", { "exceptRange": true }]
// Invalid configuration:
// "yoda": ["warn", "never", { "exceptRange": true }, 5]
// "yoda": ["error", { "exceptRange": true }, "never"]
module.exports = {
meta: {
schema: [
{
enum: ["always", "never"]
},
{
type: "object",
properties: {
exceptRange: { type: "boolean" }
},
additionalProperties: false
}
]
}
};
这是等效的基于对象的模式:
¥And here is the equivalent object-based schema:
// Valid configuration:
// "yoda": "warn"
// "yoda": ["error"]
// "yoda": ["error", "always"]
// "yoda": ["error", "never", { "exceptRange": true }]
// Invalid configuration:
// "yoda": ["warn", "never", { "exceptRange": true }, 5]
// "yoda": ["error", { "exceptRange": true }, "never"]
module.exports = {
meta: {
schema: {
type: "array",
minItems: 0,
maxItems: 2,
items: [
{
enum: ["always", "never"]
},
{
type: "object",
properties: {
exceptRange: { type: "boolean" }
},
additionalProperties: false
}
]
}
}
};
对象模式在允许的范围内可以更加精确和严格。例如,下面的模式始终要求指定第一个选项(0 到 10 之间的数字),但第二个选项是可选的,并且可以是显式设置某些选项的对象,也可以是 "off"
或 "strict"
。
¥Object schemas can be more precise and restrictive in what is permitted. For example, the below schema always requires the first option to be specified (a number between 0 and 10), but the second option is optional, and can either be an object with some options explicitly set, or "off"
or "strict"
.
// Valid configuration:
// "someRule": ["error", 6]
// "someRule": ["error", 5, "strict"]
// "someRule": ["warn", 10, { someNonOptionalProperty: true }]
// Invalid configuration:
// "someRule": "warn"
// "someRule": ["error"]
// "someRule": ["warn", 15]
// "someRule": ["warn", 7, { }]
// "someRule": ["error", 3, "on"]
// "someRule": ["warn", 7, { someOtherProperty: 5 }]
// "someRule": ["warn", 7, { someNonOptionalProperty: false, someOtherProperty: 5 }]
module.exports = {
meta: {
schema: {
type: "array",
minItems: 1, // Can't specify only severity!
maxItems: 2,
items: [
{
type: "number",
minimum: 0,
maximum: 10
},
{
anyOf: [
{
type: "object",
properties: {
someNonOptionalProperty: { type: "boolean" }
},
required: ["someNonOptionalProperty"],
additionalProperties: false
},
{
enum: ["off", "strict"]
}
]
}
]
}
}
}
请记住,规则选项始终是一个数组,因此请注意不要在顶层指定非数组类型的架构。如果你的架构未在顶层指定数组,则用户永远无法启用你的规则,因为启用规则后他们的配置将始终无效。
¥Remember, rule options are always an array, so be careful not to specify a schema for a non-array type at the top level. If your schema does not specify an array at the top-level, users can never enable your rule, as their configuration will always be invalid when the rule is enabled.
这是一个总是验证失败的示例模式:
¥Here’s an example schema that will always fail validation:
// Possibly trying to validate ["error", { someOptionalProperty: true }]
// but when the rule is enabled, config will always fail validation because the options are an array which doesn't match "object"
module.exports = {
meta: {
schema: {
type: "object",
properties: {
someOptionalProperty: {
type: "boolean"
}
},
additionalProperties: false
}
}
}
注意:如果你的规则架构使用 JSON 架构 $ref
属性,则必须使用完整的 JSON 架构对象而不是位置属性架构数组。这是因为 ESLint 将数组速记转换为单个模式,而没有更新使它们不正确的引用(它们被忽略)。
¥Note: If your rule schema uses JSON schema $ref
properties, you must use the full JSON Schema object rather than the array of positional property schemas. This is because ESLint transforms the array shorthand into a single schema without updating references that makes them incorrect (they are ignored).
要了解有关 JSON 架构的更多信息,我们建议查看 JSON 结构网站 上的一些示例,或阅读免费的 理解 JSON 模式 电子书。
¥To learn more about JSON Schema, we recommend looking at some examples on the JSON Schema website, or reading the free Understanding JSON Schema ebook.
选项默认值
¥Option Defaults
规则可以为任何选项指定一个 meta.defaultOptions
默认值数组。当在用户配置中启用规则时,ESLint 将在默认元素之上递归合并任何用户提供的选项元素。
¥Rules may specify a meta.defaultOptions
array of default values for any options.
When the rule is enabled in a user configuration, ESLint will recursively merge any user-provided option elements on top of the default elements.
例如,给定以下默认值:
¥For example, given the following defaults:
export default {
meta: {
defaultOptions: [{
alias: "basic",
}],
schema: [{
type: "object",
properties: {
alias: {
type: "string"
}
},
additionalProperties: false
}]
},
create(context) {
const [{ alias }] = context.options;
return { /* ... */ };
}
}
除非用户配置指定了不同的值(例如 ["error", { alias: "complex" }]
),否则规则的运行时 alias
值将为 "basic"
。
¥The rule would have a runtime alias
value of "basic"
unless the user configuration specifies a different value, such as with ["error", { alias: "complex" }]
.
选项数组的每个元素都根据以下规则合并:
¥Each element of the options array is merged according to the following rules:
-
任何缺失值或显式用户提供的
undefined
将恢复为默认选项¥Any missing value or explicit user-provided
undefined
will fall back to a default option -
除
undefined
之外的用户提供的数组和原始值将覆盖默认选项¥User-provided arrays and primitive values other than
undefined
override a default option -
否则,用户提供的对象将合并到默认选项对象中,并替换非对象默认值
¥User-provided objects will merge into a default option object and replace a non-object default otherwise
选项默认值也将根据规则的 meta.schema
进行验证。
¥Option defaults will also be validated against the rule’s meta.schema
.
注意:ESLint 在启用其 useDefaults
选项 的情况下内部使用 Ajv 进行架构验证。用户提供的选项和 meta.defaultOptions
选项都将覆盖规则架构中指定的任何默认值。ESLint 可能会在未来的主要版本中禁用 Ajv 的 useDefaults
。
¥Note: ESLint internally uses Ajv for schema validation with its useDefaults
option enabled.
Both user-provided and meta.defaultOptions
options will override any defaults specified in a rule’s schema.
ESLint may disable Ajv’s useDefaults
in a future major version.
访问 Shebang
¥Accessing Shebangs
Shebangs (#!) 由 "Shebang"
类型的唯一标记表示。它们被视为注释,可以通过 访问注释 部分中概述的方法访问,例如 sourceCode.getAllComments()
。
¥Shebangs (#!) are represented by the unique tokens of type "Shebang"
. They are treated as comments and can be accessed by the methods outlined in the Accessing Comments section, such as sourceCode.getAllComments()
.
访问变量范围
¥Accessing Variable Scopes
SourceCode#getScope(node)
方法返回给定节点的范围。这是查找有关给定范围内的变量以及它们在其他范围内的使用方式的信息的有用方法。
¥The SourceCode#getScope(node)
method returns the scope of the given node. It is a useful method for finding information about the variables in a given scope and how they are used in other scopes.
范围类型
¥Scope types
下表包含 AST 节点类型列表以及它们对应的范围类型。有关作用域类型的更多信息,请参阅 Scope
对象文档。
¥The following table contains a list of AST node types and the scope type that they correspond to. For more information about the scope types, refer to the Scope
object documentation.
AST 节点类型 | 范围类型 |
---|---|
Program |
global |
FunctionDeclaration |
function |
FunctionExpression |
function |
ArrowFunctionExpression |
function |
ClassDeclaration |
class |
ClassExpression |
class |
BlockStatement ※1 |
block |
SwitchStatement ※1 |
switch |
ForStatement ※2 |
for |
ForInStatement ※2 |
for |
ForOfStatement ※2 |
for |
WithStatement |
with |
CatchClause |
catch |
其他的 | ※3 |
※1 仅当配置的解析器提供块作用域功能时。如果 parserOptions.ecmaVersion
不小于 6
,则默认解析器提供块作用域功能。
※2 仅当 for
语句将迭代变量定义为块作用域变量(例如 for (let i = 0;;) {}
)时。
※3 作用域 具有自己范围的最近祖级节点。如果最近的祖级节点有多个范围,则它选择最里面的范围(例如,如果 Program#sourceType
是 "module"
,则 Program
节点具有 global
范围和 module
范围。最里面的范围是 module
范围。)。
¥**※1** Only if the configured parser provided the block-scope feature. The default parser provides the block-scope feature if parserOptions.ecmaVersion
is not less than 6
.
※2 Only if the for
statement defines the iteration variable as a block-scoped variable (E.g., for (let i = 0;;) {}
).
※3 The scope of the closest ancestor node which has own scope. If the closest ancestor node has multiple scopes then it chooses the innermost scope (E.g., the Program
node has a global
scope and a module
scope if Program#sourceType
is "module"
. The innermost scope is the module
scope.).
范围变量
¥Scope Variables
Scope#variables
属性包含 Variable
对象 的数组。这些是在当前范围内声明的变量。你可以使用这些 Variable
对象来跟踪整个模块中对变量的引用。
¥The Scope#variables
property contains an array of Variable
objects. These are the variables declared in current scope. You can use these Variable
objects to track references to a variable throughout the entire module.
在每个 Variable
内部,Variable#references
属性包含一个 Reference
对象 数组。Reference
数组包含模块源代码中引用变量的所有位置。
¥Inside of each Variable
, the Variable#references
property contains an array of Reference
objects. The Reference
array contains all the locations where the variable is referenced in the module’s source code.
同样在每个 Variable
内部,Variable#defs
属性包含一个 Definition
对象 数组。你可以使用 Definitions
查找定义变量的位置。
¥Also inside of each Variable
, the Variable#defs
property contains an array of Definition
objects. You can use the Definitions
to find where the variable was defined.
全局变量具有以下附加属性:
¥Global variables have the following additional properties:
-
Variable#writeable
(boolean | undefined
) …如果是true
,这个全局变量可以赋任意值。如果是false
,这个全局变量是只读的。¥
Variable#writeable
(boolean | undefined
) … Iftrue
, this global variable can be assigned arbitrary value. Iffalse
, this global variable is read-only. -
Variable#eslintExplicitGlobal
(boolean | undefined
) …如果为true
,则此全局变量由源代码文件中的/* globals */
指令注释定义。¥
Variable#eslintExplicitGlobal
(boolean | undefined
) … Iftrue
, this global variable was defined by a/* globals */
directive comment in the source code file. -
Variable#eslintExplicitGlobalComments
(Comment[] | undefined
) …在源代码文件中定义此全局变量的/* globals */
指令注释数组。如果没有/* globals */
指令注释,则此属性为undefined
。¥
Variable#eslintExplicitGlobalComments
(Comment[] | undefined
) … The array of/* globals */
directive comments which defined this global variable in the source code file. This property isundefined
if there are no/* globals */
directive comments. -
Variable#eslintImplicitGlobalSetting
("readonly" | "writable" | undefined
) …配置文件中配置的值。如果有/* globals */
指令注释,这可以与variable.writeable
不同。¥
Variable#eslintImplicitGlobalSetting
("readonly" | "writable" | undefined
) … The configured value in config files. This can be different fromvariable.writeable
if there are/* globals */
directive comments.
使用 SourceCode#getScope()
跟踪变量的例子,参考源码,内置规则如下:
¥For examples of using SourceCode#getScope()
to track variables, refer to the source code for the following built-in rules:
-
no-shadow:在
Program
节点调用sourceCode.getScope()
并检查所有子作用域以确保变量名称未在较低作用域中重用。(no-shadow 文档)¥no-shadow: Calls
sourceCode.getScope()
at theProgram
node and inspects all child scopes to make sure a variable name is not reused at a lower scope. (no-shadow documentation) -
no-redeclare:在每个作用域调用
sourceCode.getScope()
以确保变量未在同一作用域中声明两次。(no-redeclare 文档)¥no-redeclare: Calls
sourceCode.getScope()
at each scope to make sure that a variable is not declared twice in the same scope. (no-redeclare documentation)
将变量标记为已使用
¥Marking Variables as Used
某些 ESLint 规则,例如 no-unused-vars
,检查是否使用了变量。ESLint 本身只知道变量访问的标准规则,因此访问变量的自定义方式可能不会注册为 “used”。
¥Certain ESLint rules, such as no-unused-vars
, check to see if a variable has been used. ESLint itself only knows about the standard rules of variable access and so custom ways of accessing variables may not register as “used”.
为此,你可以使用 sourceCode.markVariableAsUsed()
方法。此方法有两个参数:要标记为已使用的变量的名称和指示你正在工作的范围的选项参考节点。这是一个例子:
¥To help with this, you can use the sourceCode.markVariableAsUsed()
method. This method takes two arguments: the name of the variable to mark as used and an option reference node indicating the scope in which you are working. Here’s an example:
module.exports = {
create: function(context) {
var sourceCode = context.sourceCode;
return {
ReturnStatement(node) {
// look in the scope of the function for myCustomVar and mark as used
sourceCode.markVariableAsUsed("myCustomVar", node);
// or: look in the global scope for myCustomVar and mark as used
sourceCode.markVariableAsUsed("myCustomVar");
}
}
// ...
}
};
这里,myCustomVar
变量被标记为相对于 ReturnStatement
节点已使用,这意味着 ESLint 将从最接近该节点的范围开始搜索。如果省略第二个参数,则使用顶层范围。(对于 ESM 文件,顶层作用域是模块作用域;对于 CommonJS 文件,顶层作用域是第一个函数作用域。)
¥Here, the myCustomVar
variable is marked as used relative to a ReturnStatement
node, which means ESLint will start searching from the scope closest to that node. If you omit the second argument, then the top-level scope is used. (For ESM files, the top-level scope is the module scope; for CommonJS files, the top-level scope is the first function scope.)
访问代码路径
¥Accessing Code Paths
ESLint 在遍历 AST 时分析代码路径。你可以通过与代码路径相关的七个事件来访问代码路径对象。有关详细信息,请参阅 代码路径分析。
¥ESLint analyzes code paths while traversing AST. You can access code path objects with seven events related to code paths. For more information, refer to Code Path Analysis.
弃用的 SourceCode
方法
¥Deprecated SourceCode
Methods
请注意,以下 SourceCode
方法已被弃用,并将在 ESLint 的未来版本中删除:
¥Please note that the following SourceCode
methods have been deprecated and will be removed in a future version of ESLint:
-
getTokenOrCommentBefore()
:由带有{ includeComments: true }
选项的SourceCode#getTokenBefore()
替换。¥
getTokenOrCommentBefore()
: Replaced bySourceCode#getTokenBefore()
with the{ includeComments: true }
option. -
getTokenOrCommentAfter()
:由带有{ includeComments: true }
选项的SourceCode#getTokenAfter()
替换。¥
getTokenOrCommentAfter()
: Replaced bySourceCode#getTokenAfter()
with the{ includeComments: true }
option. -
isSpaceBetweenTokens()
:替换为SourceCode#isSpaceBetween()
¥
isSpaceBetweenTokens()
: Replaced bySourceCode#isSpaceBetween()
-
getJSDocComment()
规则单元测试
¥Rule Unit Tests
ESLint 提供了 RuleTester
实用程序,可以轻松编写规则测试。
¥ESLint provides the RuleTester
utility to make it easy to write tests for rules.
规则命名约定
¥Rule Naming Conventions
虽然你可以为自定义规则指定任何名称,但核心规则具有命名约定。将这些相同的命名约定应用于你的自定义规则可能会更清楚。要了解更多信息,请参阅 核心规则命名约定 文档。
¥While you can give a custom rule any name you’d like, the core rules have naming conventions. It could be clearer to apply these same naming conventions to your custom rule. To learn more, refer to the Core Rule Naming Conventions documentation.
运行时规则
¥Runtime Rules
ESLint 与其他 linter 的不同之处在于能够在运行时定义自定义规则。这非常适合特定于你的项目或公司的规则,并且对于 ESLint 附带或包含在插件中没有意义。只需编写你的规则并在运行时包含它们。
¥The thing that makes ESLint different from other linters is the ability to define custom rules at runtime. This is perfect for rules that are specific to your project or company and wouldn’t make sense for ESLint to ship with or be included in a plugin. Just write your rules and include them at runtime.
运行时规则的编写格式与所有其他规则相同。像创建任何其他规则一样创建你的规则,然后按照以下步骤操作:
¥Runtime rules are written in the same format as all other rules. Create your rule as you would any other and then follow these steps:
-
将所有运行时规则放在同一目录中(例如,
eslint_rules
)。¥Place all of your runtime rules in the same directory (e.g.,
eslint_rules
). -
创建一个 配置文件 并在
rules
键下指定你的规则 ID 错误级别。除非配置文件中的值为"warn"
或"error"
,否则你的规则将不会运行。¥Create a configuration file and specify your rule ID error level under the
rules
key. Your rule will not run unless it has a value of"warn"
or"error"
in the configuration file. -
使用
--rulesdir
选项运行 命令行接口 以指定运行时规则的位置。¥Run the command line interface using the
--rulesdir
option to specify the location of your runtime rules.
配置文件规则性能
¥Profile Rule Performance
ESLint 有一个内置的方法来跟踪单个规则的性能。设置 TIMING
环境变量将在 linting 完成后触发显示十个运行时间最长的规则,以及它们各自的运行时间(规则创建 + 规则执行)和相对性能影响占总规则处理时间(规则创建)的百分比 + 规则执行)。
¥ESLint has a built-in method to track the performance of individual rules. Setting the TIMING
environment variable will trigger the display, upon linting completion, of the ten longest-running rules, along with their individual running time (rule creation + rule execution) and relative performance impact as a percentage of total rule processing time (rule creation + rule execution).
$ TIMING=1 eslint lib
Rule | Time (ms) | Relative
:-----------------------|----------:|--------:
no-multi-spaces | 52.472 | 6.1%
camelcase | 48.684 | 5.7%
no-irregular-whitespace | 43.847 | 5.1%
valid-jsdoc | 40.346 | 4.7%
handle-callback-err | 39.153 | 4.6%
space-infix-ops | 35.444 | 4.1%
no-undefined | 25.693 | 3.0%
no-shadow | 22.759 | 2.7%
no-empty-class | 21.976 | 2.6%
semi | 19.359 | 2.3%
要显式测试一条规则,请组合 --no-eslintrc
和 --rule
选项:
¥To test one rule explicitly, combine the --no-eslintrc
, and --rule
options:
$ TIMING=1 eslint --no-eslintrc --rule "quotes: [2, 'double']" lib
Rule | Time (ms) | Relative
:------|----------:|--------:
quotes | 18.066 | 100.0%
要查看更长的结果列表(超过 10 个),请将环境变量设置为另一个值,例如 TIMING=50
或 TIMING=all
。
¥To see a longer list of results (more than 10), set the environment variable to another value such as TIMING=50
or TIMING=all
.
要获得更精细的计时信息(每个文件每个规则),请改用 stats
选项。
¥For more granular timing information (per file per rule), use the stats
option instead.