java编写两个自定义异常
At Testim.io we care about code quality and UX. For this reason, we use various tools that make development easier and more accurate. Among others, we use Stylelint to lint our SCSS and CSS files. One of the powerful features of stylelint is the ability to add rules of your own, which will fit your project’s needs. While stylelint provides an API for adding custom rules, it can be a bit confusing when doing so for the first time.
在Testim.io,我们关心代码质量和UX。 因此,我们使用各种工具使开发更容易,更准确。 除其他外,我们使用Stylelint整理我们的SCSS和CSS文件。 stylelint的强大功能之一就是能够添加自己的规则,从而满足您项目的需求。 尽管stylelint提供了用于添加自定义规则的API,但第一次这样做可能会有些混乱。
In this blog post, we will go through the steps for adding a new custom stylelint rule to your project:
在此博客文章中,我们将逐步完成向您的项目添加新的自定义stylelint规则的步骤:
- Declaring and creating the plugin 声明和创建插件
- Adding a rule to the plugin向插件添加规则
- Implementing the linting function along with auto-fix support实施linting功能以及自动修复支持
- Integrating the plugin with your project’s Stylelint configuration将插件与项目的Stylelint配置集成
背景故事(Background story)
In our application’s codebase, we store commonly used colors in variables. This makes color theme changes very quick and easy. While developing a visual component, we use Invision’s mockups as a reference. Invision isn’t aware of the color variables we use. Thus, Copying styles from Invision involves searching for the colors’ variables (e.g. replace #ff6363
with $color-red1
).
在应用程序的代码库中,我们将常用颜色存储在变量中。 这使颜色主题更改变得非常快速和容易。 在开发视觉组件时,我们使用Invision的模型作为参考。 Invision并不了解我们使用的颜色变量。 因此,从Invision复制样式涉及搜索颜色的变量(例如,将#ff6363
替换为$color-red1
)。
This seems like an easy thing to do: use “find anywhere” and look for this color. Yet, the process becomes cumbersome — especially if we include many colors. Additionally, in some cases of legacy code, the variable ($color-red1
) was not used. Hence, we can find the same color (#ff6363
) scattered in the codebase. In such cases, the developer has to find the correct declaration in all search results.
这似乎很容易做到:使用“在任何地方查找”并寻找该颜色。 但是,该过程变得很麻烦-尤其是当我们包含多种颜色时。 此外,在某些遗留代码情况下,未使用变量( $color-red1
)。 因此,我们可以在代码库中找到相同的颜色( #ff6363
)。 在这种情况下,开发人员必须在所有搜索结果中找到正确的声明。
In order to solve this inconvenience, we wrote a custom stylelint rule. It suggests the correct variable name, and even auto-fixes the errors. How convenient!
为了解决这种不便,我们编写了一个自定义stylelint规则。 它建议使用正确的变量名,甚至可以自动修复错误。 多么方便!

In the following paragraphs, we will describe the steps for adding a custom rule of your own. As an abbreviated example, we’ll write a rule which will replace the expression blue
with the hex value #0000FF
.
在以下段落中,我们将描述添加您自己的自定义规则的步骤。 作为一个简短的示例,我们将编写一条规则,该规则将将表达式blue
替换为十六进制值#0000FF
。
编写插件-第一步 (Writing the Plugin — First Steps)
Let’s start with creating a file that will contain the rule itself — in our case, it’s no-color-blue.js
.
让我们从创建一个包含规则本身的文件开始-在我们的例子中,它是no-color-blue.js
。
Next, you’ll need to define your rule. This way stylelint will know what to run when the rule appears in the configurations:
接下来,您需要定义规则。 这样,当规则出现在配置中时,stylelint将知道要运行什么:
// no-color-blue.js
const stylelint = require('stylelint');
const { ruleMessages, validateOptions } = stylelint.utils;
const ruleName = 'testim-plugin/no-color-blue';
const messages = ruleMessages(ruleName, {
//… linting messages can be specified here
});
Your file will need to export three things: the rule name, the messages that it shows, and the rule itself.
您的文件将需要导出三件事:规则名称,它显示的消息以及规则本身。
module.exports.ruleName = ruleName;
module.exports.messages = messages;
module.exports = stylelint.createPlugin(ruleName, function ruleFunction(primaryOption, secondaryOptionObject, context) {
return function lint(postcssRoot, postcssResult) {
// ...
}});
If it still doesn’t make much sense to you, that’s ok! In the next sections we’ll explain each part.
如果这对您仍然没有意义,那就可以了! 在下一节中,我们将解释每个部分。
创建一个插件 (Creating a Plugin)
We use stylelint.createPlugin
to create and register a stylelint rule. It receives two arguments: the rule name, and the ruleFunction itself.stylelint calls ruleFunction
if the rule is used in the linting process. The function receives the configured options, along with the linting context
object. The lint function (that ruleFunction
returns) will run on each file that is being linted. This is the actual core of the rule which will report the output for the linting process.Let’s take a deeper look at ruleFunction
and lint
.
我们使用stylelint.createPlugin
创建和注册一个stylelint规则。 它接收两个参数:规则名称和ruleFunction ruleFunction
如果在插入过程中使用了规则,stylelint会调用ruleFunction
。 该函数接收配置的选项以及棉绒context
对象。 lint函数( ruleFunction
返回的函数)将在每个被插入的文件上运行。 这是规则的实际核心,它将报告ruleFunction
进程的输出。让我们更深入地了解ruleFunction
和lint
。
向插件添加规则 (Adding a Rule to the Plugin)
As mentioned before, stylelint calls ruleFunction for each single linting “process”. Stylelint’s rule support options. These can be used to customize the rule’s behavior from the stylelint’s configuration. For example, most rules support the severity option. When using your rule, the ruleFunction
will be called with the matching options (primary and secondary).
如前所述,stylelint为每个单一的“进程”调用ruleFunction。 Stylelint的规则支持选项。 这些可用于根据stylelint的配置来自定义规则的行为。 例如,大多数规则支持严重性选项。 使用规则时,将使用匹配选项(主要和次要)调用ruleFunction
。
Furthermore, stylelint provides a handy validateOptions
function. Use it to automatically report errors if the user passed invalid options. Stylelint will add the errors to the linting result (called here postcssResult
). The documentation isn’t too extensive, but the source code has some good comments.The third argument of ruleFunction
is the context
object. It is mainly used for supporting auto-fix (more on that later).
此外,stylelint提供了方便的validateOptions
函数。 如果用户传递了无效的选项,可使用它自动报告错误。 Stylelint会将错误添加到postcssResult
结果中(在此处称为postcssResult
)。 文档虽然不太广泛,但是源代码中有一些不错的注释ruleFunction
第三个参数是context
对象。 它主要用于支持自动修复(稍后会详细介绍)。
The following snippet should make things clearer:
以下代码片段应使情况更清楚:
module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOption, secondaryOptionObject, context) {
return function lint(postcssRoot, postcssResult) {
const validOptions = validateOptions(
postcssResult,
ruleName,
{
//Options schema goes here
}
);
if (!validOptions) { //If the options are invalid, don't lint
return;
}
const shouldDoExtraCoolStuff = secondaryOptionObject.doStuff; //Parse the options to customize behaviour
const isAutoFixing = Boolean(context.fix); //context.fix will be "true" if auto-fix mode is active
//...
}
}
We’re done with setting up the rule. Now, let’s write the lint
function which holds the core logic of the rule.
设置规则已经完成。 现在,让我们编写包含规则核心逻辑的lint
函数。
执行整理 (Performing the Linting)
After creating your rule, stylelint will run PostCSS on each linted file. Next, in the linting phase, stylelint will call the custom rule’s lint
function. The lint
function is at the core of your rule. It receives two arguments:
创建规则后,stylelint将在每个文件文件上运行PostCSS。 接下来,在lint
阶段,stylelint将调用自定义规则的lint
功能。 lint
功能是您规则的核心。 它收到两个参数:
postcssRoot
— the parsed AST. It “represents a CSS file and contains all its parsed nodes”.postcssRoot
—解析的AST。 它“代表一个CSS文件,并包含所有已解析的节点” 。postcssResult
— the LazyResult which will accumulate the output of your rule’s linting.postcssResult
— LazyResult ,它将累积您规则输出的输出。
Usually, the lint
function will:
通常, lint
函数将执行以下操作:
“Walk” through the AST (the parsed CSS nodes). Use one of the
root.walk
methods for this task.- Detect invalid nodes. 检测无效的节点。
- Report these nodes (or fix them, depending on the “fix” flag). 报告这些节点(或修复它们,具体取决于“修复”标志)。
Let’s examine the complete example of our rule. Reminder — the rule forbids the color name blue
and expects it to be replaced with the hex RGB color #0000FF
.
让我们研究一下规则的完整示例。 提醒-规则禁止使用颜色名称blue
并希望将其替换为十六进制RGB颜色#0000FF
。
//no-blue-color.js
const stylelint = require('stylelint');
const { report, ruleMessages, validateOptions } = stylelint.utils;
const ruleName = 'testim-plugin/no-blue-color';
const messages = ruleMessages(ruleName, {
expected: (unfixed, fixed) => `Expected "${unfixed}" to be "${fixed}"`,
});
module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOption, secondaryOptionObject, context) {
return function lint(postcssRoot, postcssResult) {
const validOptions = validateOptions(
postcssResult,
ruleName,
{
//No options for now...
}
);
if (!validOptions) { //If the options are invalid, don't lint
return;
}
const isAutoFixing = Boolean(context.fix);
postcssRoot.walkDecls(decl => { //Iterate CSS declarations
const hasBlue = decl.value.includes('blue');
if (!hasBlue) {
return; //Nothing to do with this node - continue
}
if (isAutoFixing) { //We are in “fix” mode
const newValue = decl.value.replace('blue', '#0000FF');
//Apply the fix. It's not pretty, but that's the way to do it
if (decl.raws.value) {
decl.raws.value.raw = newValue;
} else {
decl.value = newValue;
}
} else { //We are in “report only” mode
report({
ruleName,
result: postcssResult,
message: messages.expected('blue', '#0000FF'), // Build the reported message
node: decl, // Specify the reported node
word: 'blue', // Which exact word caused the error? This positions the error properly
});
}
});
};
});
module.exports.ruleName = ruleName;
module.exports.messages = messages;
That’s it! All that’s left is adding the rule to stylelint’s config.
而已! 剩下的就是将规则添加到stylelint的配置中。
自定义规则集成 (Custom Rule Integration)
Edit your project’s stylelint configuration (e.g. .stylelintrc.json
). Under the “plugins” configuration value, add a path to your plugin’s file. All that’s left is activating your rule, so stylelint will actually run it. Do this by adding your rule to the “rules” configuration value.A minimal .stylelintrc
file will look like so:
编辑项目的stylelint配置(例如.stylelintrc.json
)。 在“插件”配置值下,向您的插件文件添加路径。 剩下的就是激活您的规则,因此stylelint将实际运行它。 通过将规则添加到“规则”配置值中来执行此操作。最小的.stylelintrc
文件如下所示:
//.stylelintrc.json
{
"plugins": [
"./no-blue-color.js"
],
"rules": {
"testim-plugin/no-blue-color": true
}
}
Please note that for enabling a rule, stylelint requires passing options to it. Even if the rule has no options (like our no-color-blue
example), it is still required to pass a true
option to it. Without it, stylelint will ignore the rule.
请注意,要启用规则,stylelint需要向其传递选项。 即使该规则没有选项(例如我们的no-color-blue
示例),仍然需要将true
选项传递给它。 没有它,stylelint将忽略该规则。
That’s it! You and your team can now enjoy your custom linting errors.
而已! 您和您的团队现在可以享受您的自定义棉绒错误。

概要 (Summary)
Stylelint is a very useful linting tool. It has many advantages when collaborating on common SCSS and CSS files. It comes with a vast variety of existing rules. Yet, they can’t always answer all your needs. At some point, you’ll need a linting rule that is yet to exist. It might be the project’s structure, your team’s conventions, or anything else. In these cases, custom rules will be very helpful.
Stylelint是非常有用的整理工具。 在共同的SCSS和CSS文件上进行协作时,它具有许多优点。 它带有各种各样的现有规则。 但是,他们不能总是满足您的所有需求。 在某个时候,您将需要一条不存在的规则。 可能是项目的结构,团队的约定或其他任何内容。 在这些情况下,自定义规则将非常有帮助。
I hope that after reading this post, you will be able to quickly create and integrate your own stylelint rules. This way, you will keep a higher level of code quality while respecting your project’s requirements.
我希望阅读本文后,您将能够快速创建和集成自己的stylelint规则。 这样,您可以在遵守项目要求的同时保持更高级别的代码质量。
进一步阅读 (Further reading)
Awesome Stylelint — A list of awesome stylelint configs, plugins, etc. [EDIT] — This post is now in Awesome List!
Awesome Stylelint —令人敬畏的stylelint配置,插件等列表。 [编辑]-此帖子现在在Awesome列表中!
翻译自: https://medium.com/@omril321/writing-your-first-custom-stylelint-rule-a9620bb2fb73
java编写两个自定义异常