Index

自定义规则

你可以创建自定义规则来与 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) 包含该规则的元数据:

  • type:(string) 表示规则的类型,它可以是 "problem""suggestion""layout" 中的一个:

    • "problem":这个规则是识别那些会导致错误或可能引起混乱行为的代码。开发者应将其视为高优先级问题来解决。
    • "suggestion":规则是确定可以以更好的方式完成的事情,但如果不更改代码就不会发生错误。
    • "layout":该规则主要关注空白符、分号、逗号和括号,所有这些都是决定代码外观而非执行方式的程序部分。这些规则作用于抽象语法树(AST)中未指定的代码部分。

    可以与命令行选项 --fix-type 一起使用规则类型,以指定要应用的修复类型。

  • docs:(object) 常用于文档生成和工具的属性。核心规则必需,自定义规则可选。自定义规则可以根据需要在此处包含其他属性。

    • description:(string) 提供规则的简要描述。对于核心规则,这将在 rules index 中使用。
    • dialects:(string[]) 该规则旨在检查的语言方言。例如,["JavaScript", "TypeScript"]
    • frozen:(boolean) 对于核心规则,指定该规则是否已冻结并且不再接受功能请求。
    • recommended:(unknown) 对于核心规则,这是一个布尔值,用于指定该规则是否由 @eslint/jsrecommended 配置启用。
    • url:(string) 指定可以访问完整文档的 URL。代码编辑器通常使用它在高亮的规则违规上提供一个有用的链接。
  • messages:(object) 一个包含该规则的违规和建议消息的对象。对于核心规则是必需的,对于自定义规则是可选的。消息可以在 context.report() 调用中通过其键 (messageIds) 引用。更多信息请参见 messageIds

  • fixable:(string) 如果 命令行 上的 --fix 选项自动修复规则报告的问题,则为 "code""whitespace"

    重要: fixable 属性是可修复规则的必需项。如果未指定此属性,每当规则尝试生成修复时,ESLint 都会抛出错误。如果规则不可修复,则省略 fixable 属性。

  • hasSuggestions:(boolean) 指定规则是否可以返回建议(如果省略,默认为 false)。

    重要提示: 对于提供建议的规则,hasSuggestions 属性是必需的。如果未将此属性设置为 true,当规则尝试生成建议时,ESLint 将抛出错误。如果规则不提供建议,请省略 hasSuggestions 属性。

  • schema:(object | array | false) 指定 选项,以便 ESLint 可以防止无效的 规则配置。当规则有选项时,此项为必填。

  • defaultOptions:(array) 指定规则的默认选项。如果存在,用户在其配置中提供的任何选项将会递归地合并到这些默认选项上。

  • languages:(array) 指定该规则设计适用的语言。每个条目都是 "pluginName/languageName" 格式的字符串(例如,"js/js""markdown/gfm")。特殊值:

    • "*"——这个规则适用于任何语言。
    • "pluginName/*" —— 该规则适用于所提供插件支持的任何语言。

    如果未指定 languages,则假定该规则适用于所有语言。 当指定了 languages 且没有条目与当前使用的语言匹配时,ESLint 会抛出错误。

    // Rule only runs when the active language is the built-in JavaScript language
    meta: {
        languages: ["js/js"],
    }
    
    // Rule runs with any language from the "markdown" plugin
    meta: {
        languages: ["markdown/*"],
    }
    
    // Rule runs with any language
    meta: {
        languages: ["*"],
    }
    

    语言标识符按以下顺序匹配:

    1. 通配符 "*" — 匹配任何语言。
    2. 直接字符串匹配 — 条目完全等于当前语言字符串(例如,"test/lang")。
    3. "plugin/*" 通配符 — 匹配其插件名称(或 meta.namespace)等于条目插件部分的任何语言。
    4. 命名空间匹配 — 当插件的 meta.namespace 等于条目中的插件部分时,使用不同名称注册的插件可能会被匹配。
    // Rule runs with a specific language from a plugin whose meta.namespace is "markdown"
    // (e.g., the plugin is registered as "md" but declares meta.namespace = "markdown")
    meta: {
        languages: ["markdown/gfm"],
    }
    
  • deprecated:(boolean | DeprecatedInfo) 表示该规则是否已被弃用。如果规则未被弃用,可以省略 deprecated 属性。有一个专门的页面用于 DeprecatedInfo

  • replacedBy:(array不推荐使用,请改用 meta.deprecated.replacedBy。) 对于不推荐使用的规则,请指定替代规则。

create():返回一个对象,该对象包含 ESLint 在遍历 JavaScript 代码的抽象语法树(AST,由 ESTree 定义)时调用以“访问”节点的方法:

  • 如果一个键是节点类型或一个 选择器,ESLint 会在向下遍历树时调用该 访问者 函数。
  • 如果一个键是节点类型或一个 selector 加上 :exit,ESLint 会在向 遍历树时调用该 visitor 函数。
  • 如果一个键是事件名称,ESLint 会调用该 handler 函数进行 代码路径分析

规则可以使用当前节点及其周围的树来报告或修复问题。

🌐 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。
  • filename:(string) 与源相关的文件名。
  • physicalFilename:(string) 在对文件进行 lint 时,它会提供磁盘上文件的完整路径,而不包含任何代码块信息。对文本进行 lint 时,它会提供传递给 —stdin-filename 的值,或者如果未指定,则提供 <text> 的值。
  • cwd:(string) 传递给 Lintercwd 选项。它是一个目录的路径,该目录应被视为当前工作目录。
  • options:(array) 此规则的已配置选项数组。此数组不包括规则严重性(参见专用部分)。
  • sourceCode:(object) 一个 SourceCode 对象,你可以用它来处理传递给 ESLint 的源代码(参见 访问源代码)。
  • settings:(object) 配置中的共享设置
  • languageOptions:(object) 每个属性的更多详情
    • sourceType:('script' | 'module' | 'commonjs') 当前文件的模式。
    • ecmaVersion:(number) 用于解析当前文件的 ECMA 版本。
    • parser:(object):用于解析当前文件的解析器。
    • parserOptions:(object) 为此文件配置的解析器选项。
    • globals:(object) 指定的全局变量。

此外,context 对象具有以下方法:

🌐 Additionally, the context object has the following methods:

  • report(descriptor)。报告代码中的一个问题(请参见专用部分)。

注意: ESLint 的早期版本在 context 对象上支持附加方法。这些方法在新格式中已被移除,不应依赖这些方法。

报告问题

🌐 Report 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)。
  • message:(string) 问题消息(替代 messageId)。
  • node:(可选 object) 这可以是与问题相关的 AST 节点、标记或注释。如果存在且未指定 loc,则节点的起始位置将用作问题的位置。
  • loc:(可选 object)指定问题的位置。如果同时指定了 locnode,则位置将使用 loc 而不是 node
    • start:起始位置的对象。
      • line:(number) 问题发生的以1为起始的行号。
      • column:(number) 问题发生的以 0 为起始的列号。
    • end:结束位置的对象。
      • line:(number) 问题发生的以1为起始的行号。
      • column:(number) 问题发生的以 0 为起始的列号。
  • data:(可选 object) 占位符message 数据。
  • fix(fixer):(可选 function) 应用一个 修复 来解决该问题。

请注意,至少需要 nodeloc 中的一个。

🌐 Note that at least one of node or loc is required.

最简单的例子是只使用 nodemessage

🌐 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.

使用消息占位符

🌐 Use 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

🌐 messageIds

messageId 是在 context.report() 调用中报告消息的推荐方法,因为它具有以下优点:

  • 规则违规消息可以存储在中央 meta.messages 对象中,以便于管理。
  • 规则违规消息不需要在规则文件和规则测试文件中重复。
  • 因此,更改规则违规消息的门槛较低,鼓励更频繁地做出贡献以改进和优化它们,以实现最大的清晰度和实用性。

规则文件:

🌐 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 函数的规则没有 导出 meta.fixable 属性,ESLint 将抛出错误。

fixer 对象具有以下方法:

🌐 The fixer object has the following methods:

  • insertTextAfter(nodeOrToken, text):在给定的节点或标记之后插入文本。
  • insertTextAfterRange(range, text):在给定范围后插入文本。
  • insertTextBefore(nodeOrToken, text):在给定节点或标记之前插入文本。
  • insertTextBeforeRange(range, text):在给定范围之前插入文本。
  • remove(nodeOrToken):删除给定的节点或令牌。
  • removeRange(range):删除给定范围内的文本。
  • replaceText(nodeOrToken, text):替换给定节点或标记中的文本。
  • replaceTextRange(range, text):替换给定范围内的文本。

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 对象。
  • 一个包含 fixing 对象的数组。
  • 一个可迭代对象,用于枚举 fixing 对象。特别地,fix() 函数可以是一个生成器。

如果你创建一个返回多个 fixing 对象的 fix() 函数,这些 fixing 对象不能重叠。

🌐 If you make a fix() function which returns multiple fixing objects, those fixing objects must not overlap.

修复的最佳实践:

🌐 Best practices for fixes:

  1. 避免任何可能改变代码运行时行为并导致其停止工作的修复。
  2. 尽可能将修复保持最小。过大不必要的修复可能会与其他修复冲突,并阻止它们被应用。
  3. 每条消息只进行一次修复。这是强制执行的,因为你必须返回 fix() 修复操作的结果。
  4. 由于在应用第一轮修复后所有规则都会再次运行,因此规则没有必要检查修复的代码风格是否会导致另一条规则报告错误。
    • 例如,假设修复者想用引号将对象键括起来,但不确定用户更喜欢单引号还是双引号。

      { foo: 1 }
      
      // should get fixed to either
      { 'foo': 1 }
      
      // or
      { "foo": 1 }
      
    • 这个修复工具可以随意选择引号类型。如果它猜错了,生成的代码将会被 quotes 规则自动报告并修复。

注意:尽可能将修复保持最小是一种最佳实践,但在某些情况下,为了有意防止其他规则在同一轮中对周围范围进行修复,扩大修复的范围可能是正确的。例如,如果替换文本声明了一个新变量,那么在变量作用域内防止其他更改可能是有用的,因为它们可能导致名称冲突。

🌐 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 键(见 下文),以及一个 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 属性是必需的。如果规则尝试产生建议但没有 导出 此属性,ESLint 将抛出错误。

注意: 建议作为独立更改应用,不会触发多轮修复。每个建议应专注于代码中的单一更改,不应尝试符合用户定义的风格。例如,如果建议是在代码库中添加新语句,则不应尝试匹配正确的缩进或遵循用户对分号存在/缺失的偏好。这些都可以在用户触发多轮自动修复时进行更正。

建议的最佳实践:

🌐 Best practices for suggestions:

  1. 不要尝试做太多,也不要建议可能会引入大量重大更改的大型重构。
  2. 如上所述,不要试图符合用户定义的样式。

建议旨在提供修复。如果建议的 fix 函数返回了 null 或一个空数组/序列,ESLint 将自动从 lint 输出中移除整个建议。

🌐 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.

建议 messageIds

🌐 Suggestion messageIds

可以使用 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 messageIds 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 use 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[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 对象是获取有关正在进行 lint 检查的源代码的更多信息的主要对象。你可以随时使用 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;

		// ...
	},
};

一旦你有了 SourceCode 的实例,就可以在其上使用以下方法来处理代码:

🌐 Once you have an instance of SourceCode, you can use the following methods on it to work with the code:

  • getText(node):返回给定节点的源代码。省略 node 可获取整个源代码(参见专用部分)。
  • getAllComments():返回源中所有评论的数组(见专门部分)。
  • getCommentsBefore(nodeOrToken):返回一个评论标记数组,这些标记直接出现在给定节点或标记之前(参见专用部分)。
  • getCommentsAfter(nodeOrToken):返回一个评论标记数组,这些标记直接出现在给定节点或标记之后(参见专用部分)。
  • getCommentsInside(node):返回给定节点内的所有注释标记的数组(参见专用部分)。
  • isSpaceBetween(nodeOrToken, nodeOrToken):如果两个标记之间有空白字符,或者如果给定一个节点,第一个节点的最后一个标记和第二个节点的第一个标记,则返回 true。
  • isGlobalReference(node):如果标识符引用的是通过 languageOptions.globals/* global */ 注释或 ecmaVersion 配置的全局变量,并且不是由本地绑定声明的,则返回 true。
  • getFirstToken(node, skipOptions):返回表示给定节点的第一个标记。
  • getFirstTokens(node, countOptions):返回表示给定节点的前 count 个标记。
  • getLastToken(node, skipOptions):返回表示给定节点的最后一个标记。
  • getLastTokens(node, countOptions):返回表示给定节点的最后 count 个标记。
  • getTokenAfter(nodeOrToken, skipOptions):返回给定节点或标记之后的第一个标记。
  • getTokensAfter(nodeOrToken, countOptions):在给定节点或标记之后返回 count 个标记。
  • getTokenBefore(nodeOrToken, skipOptions):返回给定节点或标记之前的第一个标记。
  • getTokensBefore(nodeOrToken, countOptions):返回给定节点或标记之前的 count 个标记。
  • getFirstTokenBetween(nodeOrToken1, nodeOrToken2, skipOptions):返回两个节点或标记之间的第一个标记。
  • getFirstTokensBetween(nodeOrToken1, nodeOrToken2, countOptions):返回两个节点或标记之间的前 count 个标记。
  • getLastTokenBetween(nodeOrToken1, nodeOrToken2, skipOptions):返回两个节点或令牌之间的最后一个令牌。
  • getLastTokensBetween(nodeOrToken1, nodeOrToken2, countOptions):返回两个节点或标记之间的最后 count 个标记。
  • getTokens(node):返回给定节点的所有标记。
  • getTokensBetween(nodeOrToken1, nodeOrToken2):返回两个节点之间的所有令牌。
  • getTokenByRangeStart(index, rangeOptions):返回其范围从源中的给定索引开始的标记。
  • getNodeByRangeIndex(index):返回包含给定源索引的 AST 中最深的节点。
  • getLocFromIndex(index):返回一个包含 linecolumn 属性的对象,分别对应给定源索引的位置。line 是从1开始的,column 是从0开始的。
  • getIndexFromLoc(loc):返回源代码中给定位置的索引,其中 loc 是一个具有以 1 为基的 line 键和以 0 为基的 column 键的对象。
  • commentsExistBetween(nodeOrToken1, nodeOrToken2):如果两个节点之间存在注释,则返回 true
  • getAncestors(node):返回给定节点的祖级数组,从 AST 的根开始,一直延伸到给定节点的直接父节点。该数组不包括给定节点本身。
  • getDeclaredVariables(node):返回由给定节点声明的变量列表。此信息可用于跟踪对变量的引用。
    • 如果节点是 VariableDeclaration,则返回声明中声明的所有变量。
    • 如果节点是 VariableDeclarator,则返回在声明符中声明的所有变量。
    • 如果节点是 FunctionDeclarationFunctionExpression,除了函数参数的变量之外,还会返回函数名称的变量。
    • 如果节点是 ArrowFunctionExpression,则返回参数的变量。
    • 如果节点是 ClassDeclarationClassExpression,则返回类名的变量。
    • 如果节点是 CatchClause,则返回异常的变量。
    • 如果节点是 ImportDeclaration,则返回其所有说明符的变量。
    • 如果节点是 ImportSpecifierImportDefaultSpecifierImportNamespaceSpecifier,则返回声明的变量。
    • 否则,如果节点没有声明任何变量,则返回一个空数组。
  • getScope(node):返回给定节点的作用域。此信息可用于跟踪对变量的引用。
  • markVariableAsUsed(name, refNode):在由给定引用节点指示的作用域中,将具有指定名称的变量标记为已使用。这会影响 no-unused-vars 规则。如果找到具有给定名称的变量并将其标记为已使用,则返回 true;否则返回 false

skipOptions 是一个具有 3 个属性的对象;skipincludeCommentsfilter。默认值是 {skip: 0, includeComments: false, filter: null}

  • skip:(number) 正整数,表示跳过的标记数量。如果同时提供 filter 选项,则不会将被过滤的标记计为已跳过。
  • includeComments:(boolean) 将注释标记包含在结果中的标志。
  • filter(token):函数以一个令牌作为第一个参数。如果函数返回 false,则结果不包括该令牌。

countOptions 是一个具有 3 个属性的对象;countincludeCommentsfilter。默认值是 {count: 0, includeComments: false, filter: null}

  • count:(number) 正整数,返回令牌的最大数量。
  • includeComments:(boolean) 将注释标记包含在结果中的标志。
  • filter(token):函数以一个令牌作为第一个参数,如果函数返回 false,则结果不包括该令牌。

rangeOptions 是一个具有 1 个属性 includeComments 的对象。默认值是 {includeComments: false}

  • includeComments:(boolean) 将注释标记包含在结果中的标志。

你还可以访问一些属性:

🌐 There are also some properties you can access:

  • hasBOM:(boolean) 用于指示源代码是否包含 Unicode BOM 的标志。
  • text:(string) 正在进行代码检查的完整文本。该文本中的 Unicode BOM 已被去除。
  • ast:正在检查的代码的 AST 的 Program 节点(object)。
  • scopeManagerScopeManager 对象的代码。
  • visitorKeys:(object) 访问者键用于遍历这个 AST。
  • parserServices:(object) 包含由解析器提供的规则服务。默认的解析器不提供任何服务。然而,如果某条规则打算与自定义解析器一起使用,它可以使用 parserServices 来访问该解析器提供的任何内容。(例如,TypeScript 解析器可能提供获取给定节点计算类型的能力。)
  • lines:(array) 行数组,根据规范对换行符的定义进行分割。

每当你需要获取有关被 lint 的代码的更多信息时,你应该使用一个 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() 对于需要检查与给定节点或标记相关的注释的规则非常有用。

请记住,这些方法的结果是按需计算的。

🌐 Keep in mind that the results of these methods are calculated on demand.

你也可以通过 sourceCode 的许多方法使用 includeComments 选项访问评论。

🌐 You can also access comments through many of sourceCode’s methods using the includeComments option.

选项模式

🌐 Options Schemas

带有选项的规则必须指定一个 meta.schema 属性,它是一个 JSON Schema 格式的规则选项描述,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:

  1. 如果规则配置不是数组,则将该值封装到数组中(例如,"off" 变为 ["off"]);如果规则配置是数组,则直接使用该数组。
  2. ESLint 将规则配置数组的第一个元素验证为严重性("off""warn""error"012
  3. 如果严重性为 off0,则该规则被禁用,验证停止,忽略规则配置数组的任何其他元素。
  4. 如果启用此规则,则在严重性之后的数组中的任何元素都会被复制到 context.options 数组中(例如,["warn", "never", { someOption: 5 }] 的配置会导致 context.options = ["never", { someOption: 5 }]
  5. 该规则的模式验证在 context.options 数组上运行。

注意:这意味着规则模式无法验证严重性。规则模式仅在规则配置中严重性之后验证数组元素。规则无法知道其配置的严重性。

🌐 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 对象的数组
    • 每个元素都将与 context.options 数组中相同位置的元素进行检查。
    • 如果 context.options 数组的元素少于模式的数量,则未匹配的模式将被忽略。
    • 如果 context.options 数组的元素比模式更多,则验证失败。
    • 使用这种格式有两个重要的后果:
      • 对于用户来说,提供除了严重性之外没有任何选项给你的规则是 始终有效 的。
      • 如果你指定一个空数组,那么用户为你的规则提供任何选项(除严重性之外)将_始终是错误的_。
  • 一个完整的 JSON Schema 对象,用于验证 context.options 数组
    • 即使你的规则只接受一个选项,架构也应该假设一组选项进行验证。
    • 模式可以任意复杂,因此你可以通过 oneOfanyOf 等验证完全不同的潜在选项集。
    • 支持的 JSON 模式版本是 Draft-04,因此一些较新的特性,如 if$data,不可用。
      • 目前,明确计划不在此级别之外更新模式支持,这是出于生态系统兼容性考虑。有关更多背景,请参见此评论

例如,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 会将数组简写转换为单个模式,但不会更新引用,从而使它们不正确(会被忽略)。

要了解更多关于 JSON Schema 的信息,我们建议查看 JSON Schema 网站 上的一些示例,或阅读免费的 理解 JSON Schema 电子书。

🌐 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 都将回退到默认选项
  • 用户提供的数组和除了 undefined 之外的原始值会覆盖默认选项
  • 否则,用户提供的对象将合并到默认选项对象中,并替换非对象默认值

选项默认值也将根据规则的 meta.schema 进行验证。

🌐 Option defaults will also be validated against the rule’s meta.schema.

注意: ESLint 在启用其 useDefaults 选项 时,内部使用 Ajv 进行模式验证。
用户提供的选项和 meta.defaultOptions 选项将覆盖规则模式中指定的任何默认值。
ESLint 可能会在未来的主要版本中禁用 Ajv 的 useDefaults

访问 Shebang

🌐 Accessing Shebangs

Shebangs (#!) 由类型为 "Shebang" 的唯一标记表示。它们被视为注释,可以通过 访问注释 部分中概述的方法访问,例如 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
StaticBlock class-static-block
BlockStatement ※1 block
SwitchStatement ※1 switch
ForStatement ※2 for
ForInStatement ※2 for
ForOfStatement ※2 for
WithStatement with
CatchClause catch
其他 ※3 ※4

※1 仅当配置的解析器提供块级作用域功能时才适用。默认解析器在 languageOptions.ecmaVersion 不小于 6 时提供块级作用域功能。
※2 仅当 for 语句将迭代变量定义为块级作用域变量(例如,for (let i = 0;;) {})时才适用。
※3 最近的具有自身作用域的祖级节点的作用域。如果最近的祖级节点有多个作用域,则选择最内层的作用域(例如,如果 Program#sourceType"module",则 Program 节点有一个 global 作用域和一个 module 作用域。最内层的作用域是 module 作用域)。
※4 每个 PropertyDefinition#value 节点(可以是任何表达式节点类型)都有一个 class-field-initializer 作用域。例如,在 class C { field = 1 } 中,表示 1Literal 节点具有 class-field-initializer 作用域。如果该节点有其他作用域,class-field-initializer 作用域将是最外层的。例如,在 class C { field = () => {} } 中,ArrowFunctionExpression 节点有两个作用域:class-field-initializerfunction

范围变量

🌐 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#eslintExplicitGlobal (boolean | undefined)… 如果 true,这个全局变量是由源代码文件中的 /* globals */ 指令注释定义的。
  • Variable#eslintExplicitGlobalComments (Comment[] | undefined) … 定义此全局变量的 /* globals */ 指令注释数组,位于源代码文件中。如果没有 /* globals */ 指令注释,此属性为 undefined
  • Variable#eslintImplicitGlobalSetting ("readonly" | "writable" | undefined) … 配置文件中的配置值。如果存在 /* globals */ 指令注释,这个值可能与 variable.writeable 不同。

有关使用 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-redeclare:在每个作用域中调用 sourceCode.getScope(),以确保变量在同一作用域中不会被重复声明。(no-redeclare 文档)

将变量标记为已使用

🌐 Marking Variables as Used

某些 ESLint 规则,例如 no-unused-vars,会检查变量是否已被使用。ESLint 本身只知道变量访问的标准规则,因此以自定义方式访问变量可能不会被记录为“已使用”。

🌐 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.

规则单元测试

🌐 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 与其他代码检查工具不同的地方在于能够在运行时定义自定义规则。这对于特定于你的项目或公司的规则非常完美,而这些规则不适合随 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:

  1. 将所有运行时规则放在同一目录下(例如,eslint_rules)。
  2. 创建一个 配置文件 并在 rules 键下指定你的规则 ID 错误级别。除非在配置文件中它的值为 "warn""error",否则你的规则不会运行。
  3. 使用 --rulesdir 选项运行 命令行接口 以指定运行时规则的位置。

配置文件规则性能

🌐 Profile Rule Performance

ESLint 有一个内置方法来跟踪单个规则的性能。设置 TIMING 环境变量将在代码检查完成后显示运行时间最长的十个规则,以及它们的单独运行时间(规则创建 + 规则执行)和相对于总规则处理时间(规则创建 + 规则执行)的性能影响百分比。

🌐 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-config-lookup--rule 选项:

🌐 To test one rule explicitly, combine the --no-config-lookup and --rule options:

$ TIMING=1 eslint --no-config-lookup --rule "quotes: [2, 'double']" lib
Rule   | Time (ms) | Relative
:------|----------:|--------:
quotes |    18.066 |   100.0%

要查看更长的结果列表(超过10个),请将环境变量设置为其他值,例如 TIMING=50TIMING=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.