eslint-rule-development

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Fiori ESLint Rule Developer

Fiori ESLint 规则开发者

Add a new ESLint rule to
@sap-ux/eslint-plugin-fiori-tools
following the established patterns in the monorepo.
@sap-ux/eslint-plugin-fiori-tools
添加新的ESLint规则,请遵循单体仓库中的既定模式。

⚡ Efficiency rules — read before doing anything

⚡ 效率规则 — 开始操作前必读

  1. Use the
    Read
    tool directly
    — never
    Bash cat
    or spawn Explore subagents for file reading
  2. Read everything in one parallel batch — each fast path lists the exact files; read them all at once in a single turn
  3. Run only the new test file during development — not the full package suite:
    bash
    NODE_OPTIONS="--experimental-vm-modules" npx jest --testPathPatterns="sap-[rule-name]" --no-coverage

  1. 直接使用
    Read
    工具
    — 切勿使用
    Bash cat
    或启动Explore子代理来读取文件
  2. 批量并行读取所有文件 — 每个快速路径都会列出确切的文件;在单次操作中一次性读取所有文件
  3. 开发期间仅运行新的测试文件 — 不要运行完整的包测试套件:
    bash
    NODE_OPTIONS="--experimental-vm-modules" npx jest --testPathPatterns="sap-[rule-name]" --no-coverage

Step 1 — Identify the rule type, then read the reference file

步骤1 — 确定规则类型,然后读取参考文件

TypeUse whenReference file
Annotation ruleValidates
UI.*
OData annotations in
.xml
/
.cds
files
references/annotation.md
Manifest JSON ruleValidates
manifest.json
properties
references/manifest-json.md
Flex change file ruleValidates
webapp/changes/*.change
(Applicable only to OData V2 flex change properties)
references/flex-change.md
JavaScript / TypeScript ruleValidates JS/TS application source code (UI5 patterns, global variables, deprecated APIs)
references/js-ts-rule.md
Infer from the request:
  • Rule name
    sap-[kebab-case-name]
    pattern
  • OData version — V2 only, V4 only, or both
  • Page scope — which page types to check. Default: all page types (list report, object page, etc.) unless the spec explicitly restricts the scope. Do not limit to one page type based on the examples in the spec.
  • Auto-fix — yes/no
  • Severity
    error
    or
    warn
    . Rules in
    recommended-for-s4hana
    MUST be
    warn
    .
OData version determines the linker file — always follow the stated version:
OData versionLinker fileManifest root
V2 only
src/project-context/linker/fe-v2.ts
sap.ui.generic.app.pages.*
V4 only
src/project-context/linker/fe-v4.ts
sap.ui5.routing.targets.*
Bothboth linker filesboth roots
Read the matching reference file immediately, then read all the files it lists in a single parallel batch. If the rule spans multiple types (e.g. annotations + manifest, or manifest + flex changes), read all matching reference files and combine their templates and access patterns.

类型适用场景参考文件
注解规则验证
.xml
/
.cds
文件中的
UI.*
OData注解
references/annotation.md
Manifest JSON规则验证
manifest.json
属性
references/manifest-json.md
Flex变更文件规则验证
webapp/changes/*.change
(仅适用于OData V2的flex变更属性)
references/flex-change.md
JavaScript / TypeScript规则验证JS/TS应用源代码(UI5模式、全局变量、已弃用API)
references/js-ts-rule.md
从请求中推断:
  • 规则名称 — 遵循
    sap-[kebab-case-name]
    格式
  • OData版本 — 仅V2、仅V4或两者都支持
  • 页面范围 — 需要检查哪些页面类型。默认:所有页面类型(列表报表、对象页面等),除非规范明确限制范围。不要根据规范中的示例将范围限制为单一页面类型。
  • 自动修复 — 是/否
  • 严重程度
    error
    warn
    recommended-for-s4hana
    中的规则必须设为
    warn
OData版本决定链接器文件 — 请严格遵循指定版本:
OData版本链接器文件Manifest根节点
仅V2
src/project-context/linker/fe-v2.ts
sap.ui.generic.app.pages.*
仅V4
src/project-context/linker/fe-v4.ts
sap.ui5.routing.targets.*
两者都支持两个链接器文件两个根节点
立即读取匹配的参考文件,然后一次性批量读取其中列出的所有文件。如果规则涉及多种类型(例如注解+Manifest,或Manifest+Flex变更),请读取所有匹配的参考文件并结合它们的模板和访问模式。

Steps 2–10: Implementation Checklist

步骤2–10:实施检查清单

Step 2 — Add diagnostic constant (annotation, manifest JSON, and flex change rules only; skip for JS/TS rules)

步骤2 — 添加诊断常量(仅适用于注解、Manifest JSON和Flex变更规则;JS/TS规则可跳过)

In
packages/eslint-plugin-fiori-tools/src/language/diagnostics.ts
:
typescript
export const MY_RULE = 'sap-my-new-rule';

export interface MyRuleDiagnostic {
    type: typeof MY_RULE;
    // ... fields from the reference file's "Required diagnostic fields" table
}

// Add MyRuleDiagnostic to the Diagnostic union at the bottom
packages/eslint-plugin-fiori-tools/src/language/diagnostics.ts
中:
typescript
export const MY_RULE = 'sap-my-new-rule';

export interface MyRuleDiagnostic {
    type: typeof MY_RULE;
    // ... 参考文件中“必填诊断字段”表格中的字段
}

// 在底部将MyRuleDiagnostic添加到Diagnostic联合类型中

Step 3 — Implement the rule

步骤3 — 实现规则

Use the template from the reference file for your rule type.
Code quality requirements for every new or modified function:
  • JSDoc — add a JSDoc block (
    @param
    ,
    @returns
    ) to every new function. When modifying an existing function, update its JSDoc to reflect any signature or behaviour changes.
  • Cognitive complexity ≤ 15 — enforced by
    sonarjs/cognitive-complexity
    . If a function exceeds 15, extract branches or loops into well-named helper functions until the complexity falls within the limit. Do not inline complex logic in a single function to avoid this.
使用对应规则类型的参考文件中的模板。
所有新增或修改函数的代码质量要求:
  • JSDoc — 为每个新增函数添加JSDoc块(包含
    @param
    @returns
    )。修改现有函数时,更新其JSDoc以反映签名或行为的任何变化。
  • 认知复杂度 ≤ 15 — 由
    sonarjs/cognitive-complexity
    强制实施。如果函数复杂度超过15,将分支或循环提取到命名清晰的辅助函数中,直到复杂度符合要求。不要为了规避此限制而将复杂逻辑内联到单个函数中。

Step 4 — Register the rule

步骤4 — 注册规则

src/rules/index.ts
— add import + entry (alphabetical order):
typescript
import sapMyNewRule from './sap-my-new-rule.js';
// ...
[MY_RULE]: sapMyNewRule,
src/index.ts
— add to
fioriLanguageConfig
rules (Fiori language rules) or
baseFioriToolsRules
(JS/TS rules):
typescript
'@sap-ux/fiori-tools/sap-my-new-rule': 'warn',
If the rule should also apply to S/4HANA projects, add it to the
recommended-for-s4hana
config in
src/index.ts
as well. Rules in this config must use
'warn'
severity:
typescript
// In the recommended-for-s4hana config rules object:
'@sap-ux/fiori-tools/sap-my-new-rule': 'warn',
src/rules/index.ts
— 添加导入项和条目(按字母顺序排列):
typescript
import sapMyNewRule from './sap-my-new-rule.js';
// ...
[MY_RULE]: sapMyNewRule,
src/index.ts
— 将其添加到
fioriLanguageConfig
规则(Fiori语言规则)或
baseFioriToolsRules
(JS/TS规则)中:
typescript
'@sap-ux/fiori-tools/sap-my-new-rule': 'warn',
如果该规则也适用于S/4HANA项目,请同时将其添加到
src/index.ts
中的
recommended-for-s4hana
配置中。此配置中的规则必须使用
'warn'
严重程度:
typescript
// 在recommended-for-s4hana配置的rules对象中:
'@sap-ux/fiori-tools/sap-my-new-rule': 'warn',

Step 5 — Write tests

步骤5 — 编写测试

Use the test template from the reference file; run only the new test file (see efficiency rules at the top).
Always check
message
, never
messageId
, in
errors
arrays.
When a rule message contains interpolated data (e.g.
{{tableType}}
), checking only
messageId
would accept any value for that placeholder and miss regressions. Use the fully resolved string instead:
typescript
// ✅ Correct — verifies the interpolated value
errors: [
    {
        message:
            '"TreeTable" is not supported in the flexible column layout with a draft-enabled service.'
    }
]

// ❌ Wrong — does not verify the data interpolated into the message
errors: [{ messageId: 'sap-my-new-rule' }]
If tests show 0 errors when violations are expected, check the debug checklist at the bottom of the reference file.
使用参考文件中的测试模板;仅运行新的测试文件(参见顶部的效率规则)。
始终检查
errors
数组中的
message
,而非
messageId
当规则消息包含插值数据(例如
{{tableType}}
)时,仅检查
messageId
会接受占位符的任何值,从而遗漏回归问题。请改用完全解析后的字符串:
typescript
// ✅ 正确 — 验证插值后的值
errors: [
    {
        message:
            '"TreeTable" is not supported in the flexible column layout with a draft-enabled service.'
    }
]

// ❌ 错误 — 未验证消息中插入的数据
errors: [{ messageId: 'sap-my-new-rule' }]
如果测试显示预期存在违规但错误数为0,请查看参考文件底部的调试检查清单。

Step 6 — Write documentation

步骤6 — 编写文档

Create
packages/eslint-plugin-fiori-tools/docs/rules/sap-[rule-name].md
. Read
packages/eslint-plugin-fiori-tools/docs/rules/TEMPLATE.md
for structure. Key sections:
  • H1 title — one sentence describing the rule, with the rule ID in parentheses
  • Intro paragraph — 2–3 sentences: what it detects, why it was introduced (motivation belongs here, not in a separate H2), and what to do instead
  • ## Rule Details — how the rule works; warning message; "The following patterns are considered warnings:" + "The following patterns are not considered warnings" code examples
  • ### How to Fix — steps to remediate (omit if obvious from the examples)
  • ## False Positives — optional; include only if the rule can produce false positives
  • ## Bug Report — link to GitHub issues
  • ## Further Reading — optional; only include if you have a real, verifiable URL
创建
packages/eslint-plugin-fiori-tools/docs/rules/sap-[rule-name].md
。 阅读
packages/eslint-plugin-fiori-tools/docs/rules/TEMPLATE.md
了解文档结构。关键章节:
  • H1标题 — 一句话描述规则,括号中包含规则ID
  • 介绍段落 — 2-3句话:规则检测内容、引入原因(动机应放在此处,而非单独的H2章节)以及替代方案
  • ## 规则详情 — 规则工作方式;警告消息;“以下模式会被视为警告:” + “以下模式不会被视为警告”代码示例
  • ### 修复方法 — 修复步骤(如果从示例中可明显看出则可省略)
  • ## 误报情况 — 可选;仅当规则可能产生误报时包含
  • ## Bug报告 — GitHub问题链接
  • ## 延伸阅读 — 可选;仅包含真实可验证的URL

Step 7 — Update README

步骤7 — 更新README

In
packages/eslint-plugin-fiori-tools/README.md
, do two things:
  1. Add your new rule at the top of the rules table with
    new
    in the version column:
    markdown
    |  new  | [sap-my-new-rule](docs/rules/sap-my-new-rule.md) | Short description | | ✅ |
  2. Backfill any pending
    new
    versions
    : if any rows still show
    new
    from prior rule additions that have since been released, look up each rule's release version in
    packages/eslint-plugin-fiori-tools/CHANGELOG.md
    and replace
    new
    with that version. After this cleanup, your newly added rule should be the only row showing
    new
    .
packages/eslint-plugin-fiori-tools/README.md
中,需完成两项操作
  1. 添加新规则 — 在规则表格的顶部添加新规则,版本列标注
    new
    markdown
    |  new  | [sap-my-new-rule](docs/rules/sap-my-new-rule.md) | 简短描述 | | ✅ |
  2. 补全所有待处理的
    new
    版本
    :如果之前添加的规则仍有行显示
    new
    且已发布,请在
    packages/eslint-plugin-fiori-tools/CHANGELOG.md
    中查找每个规则的发布版本,将
    new
    替换为对应版本。完成清理后,新添加的规则应是唯一显示
    new
    的行。

Step 8 — Run full quality gates (once)

步骤8 — 运行完整质量检查(一次)

Run
lint:fix
to auto-fix ESLint errors and apply Prettier formatting across all modified files, then verify no issues remain:
bash
undefined
运行
lint:fix
自动修复ESLint错误并对所有修改文件应用Prettier格式化,然后验证是否无问题残留:
bash
undefined

Fix lint errors and apply Prettier formatting

修复lint错误并应用Prettier格式化

pnpm --filter @sap-ux/eslint-plugin-fiori-tools lint:fix
pnpm --filter @sap-ux/eslint-plugin-fiori-tools lint:fix

Verify no remaining issues

验证是否无残留问题

pnpm --filter @sap-ux/eslint-plugin-fiori-tools lint

If `lint` reports errors after `lint:fix`:

- **`sonarjs/cognitive-complexity`** — resolve per the cognitive complexity guidance in Step 3.
- **`prettier/prettier`** — a formatting issue could not be auto-fixed. Apply the suggested change manually (usually a line that is too long or a multiline expression that needs restructuring).
- **`@typescript-eslint/no-unsafe-*`** — replace `any` casts or untyped values with proper interfaces or `unknown` + type guards.

Do not proceed to Step 9 until `pnpm lint` exits with code 0.

Then confirm all tests still pass:

```bash
pnpm --filter @sap-ux/eslint-plugin-fiori-tools test
pnpm --filter @sap-ux/eslint-plugin-fiori-tools lint

如果`lint`在`lint:fix`后仍报告错误:

- **`sonarjs/cognitive-complexity`** — 按照步骤3中的认知复杂度指南解决。
- **`prettier/prettier`** — 存在无法自动修复的格式问题。手动应用建议的更改(通常是过长的行或需要重构的多行表达式)。
- **`@typescript-eslint/no-unsafe-*`** — 将`any`类型转换或未类型化的值替换为合适的接口或`unknown` + 类型守卫。

在`pnpm lint`返回代码0之前,不要进入步骤9。

然后确认所有测试仍通过:

```bash
pnpm --filter @sap-ux/eslint-plugin-fiori-tools test

Step 9 — Create changeset

步骤9 — 创建变更集

bash
pnpm cset
Select
@sap-ux/eslint-plugin-fiori-tools
, choose
minor
for new rules:
FEAT: add sap-my-new-rule rule for [short description]
bash
pnpm cset
选择
@sap-ux/eslint-plugin-fiori-tools
,为新规则选择
minor
版本:
FEAT: add sap-my-new-rule rule for [简短描述]

Step 10 — Report

步骤10 — 报告

Summarize what was done:
  • Rule name and type — rule ID and which type (annotation / manifest JSON / flex change / JS/TS)
  • Files created — rule implementation, test file, doc file
  • Files modified — diagnostics.ts, rules/index.ts, src/index.ts, README.md
  • Test results — number of valid and invalid cases, all passing
  • Changeset — package, bump type (
    minor
    ), summary line

总结已完成的工作:
  • 规则名称和类型 — 规则ID及类型(注解 / Manifest JSON / Flex变更 / JS/TS)
  • 创建的文件 — 规则实现文件、测试文件、文档文件
  • 修改的文件 — diagnostics.ts、rules/index.ts、src/index.ts、README.md
  • 测试结果 — 有效和无效用例数量,全部通过
  • 变更集 — 包、版本更新类型(
    minor
    )、摘要行

Quick Reference: Key Files

快速参考:关键文件

PurposePath
Rule implementation
packages/eslint-plugin-fiori-tools/src/rules/sap-[name].ts
Rule registry
packages/eslint-plugin-fiori-tools/src/rules/index.ts
Plugin config & exports
packages/eslint-plugin-fiori-tools/src/index.ts
Diagnostic constants
packages/eslint-plugin-fiori-tools/src/language/diagnostics.ts
Annotation helper utilities
packages/eslint-plugin-fiori-tools/src/project-context/linker/annotations.ts
Annotation index key format
packages/eslint-plugin-fiori-tools/src/project-context/parser/service.ts
(lines 50-57)
Linker types
packages/eslint-plugin-fiori-tools/src/project-context/linker/types.ts
V2 linker
packages/eslint-plugin-fiori-tools/src/project-context/linker/fe-v2.ts
V4 linker
packages/eslint-plugin-fiori-tools/src/project-context/linker/fe-v4.ts
Rule factory
packages/eslint-plugin-fiori-tools/src/language/rule-factory.ts
Rule fixer
packages/eslint-plugin-fiori-tools/src/language/rule-fixer.ts
Test helper
packages/eslint-plugin-fiori-tools/test/test-helper.ts
Rule docs template
packages/eslint-plugin-fiori-tools/docs/rules/TEMPLATE.md
README rules table
packages/eslint-plugin-fiori-tools/README.md
用途路径
规则实现
packages/eslint-plugin-fiori-tools/src/rules/sap-[name].ts
规则注册表
packages/eslint-plugin-fiori-tools/src/rules/index.ts
插件配置与导出
packages/eslint-plugin-fiori-tools/src/index.ts
诊断常量
packages/eslint-plugin-fiori-tools/src/language/diagnostics.ts
注解辅助工具
packages/eslint-plugin-fiori-tools/src/project-context/linker/annotations.ts
注解索引键格式
packages/eslint-plugin-fiori-tools/src/project-context/parser/service.ts
(第50-57行)
链接器类型
packages/eslint-plugin-fiori-tools/src/project-context/linker/types.ts
V2链接器
packages/eslint-plugin-fiori-tools/src/project-context/linker/fe-v2.ts
V4链接器
packages/eslint-plugin-fiori-tools/src/project-context/linker/fe-v4.ts
规则工厂
packages/eslint-plugin-fiori-tools/src/language/rule-factory.ts
规则修复器
packages/eslint-plugin-fiori-tools/src/language/rule-fixer.ts
测试辅助工具
packages/eslint-plugin-fiori-tools/test/test-helper.ts
规则文档模板
packages/eslint-plugin-fiori-tools/docs/rules/TEMPLATE.md
README规则表格
packages/eslint-plugin-fiori-tools/README.md

check()
context access by rule type

按规则类型划分的
check()
上下文访问方式

Rule typeUse in
check()
Why
Annotation
linkedModel.apps
for page iteration;
index.apps[appKey]
for
getIndexedServiceForMainService
Only check annotations referenced from pages — never scan all entity annotations.
pageNames
must list only pages that reference the specific annotation. See
annotation.md
for access patterns and the page-annotation-map template.
Manifest JSON
linkedModel.apps
for page iteration;
index.apps[appKey]
for
parsedApp
(manifest URI, manifestObject)
Requires linked pages to find manifest config paths
Flex change
context.sourceCode.projectContext.linkedModel.apps
Guard on
FioriChangeSourceCode
first; linked model provides change file config via
page.lookup['table']
JavaScript / TypeScriptStandard ESLint
context
— no
projectContext
JS/TS rules don't use the Fiori project model; use
Rule.RuleModule
, not
createFioriRule
规则类型
check()
中使用
原因
注解
linkedModel.apps
用于页面迭代;
index.apps[appKey]
用于
getIndexedServiceForMainService
仅检查页面引用的注解 — 切勿扫描所有实体注解。
pageNames
必须仅列出引用特定注解的页面。请查看
annotation.md
了解访问模式和页面-注解映射模板。
Manifest JSON
linkedModel.apps
用于页面迭代;
index.apps[appKey]
用于
parsedApp
(manifest URI、manifestObject)
需要链接页面来查找manifest配置路径
Flex变更
context.sourceCode.projectContext.linkedModel.apps
首先检查
FioriChangeSourceCode
;链接模型通过
page.lookup['table']
提供变更文件配置
JavaScript / TypeScript标准ESLint
context
— 不使用
projectContext
JS/TS规则不使用Fiori项目模型;使用
Rule.RuleModule
,而非
createFioriRule