dx-code-analyzer-custom-rule-create
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesedx-code-analyzer-custom-rule-create: Custom Code Analyzer Rule Authoring
dx-code-analyzer-custom-rule-create:自定义代码分析器规则编写
Ecosystem: This skill is part of a 3-skill Code Analyzer suite —(scans & results) ·dx-code-analyzer-run(setup, config, CI/CD) ·dx-code-analyzer-configure(custom rule authoring).dx-code-analyzer-custom-rule-create
Use this skill when the user needs to create a custom rule that enforces a pattern not covered by Code Analyzer's built-in rules. Supports Regex engine (text pattern matching) and PMD engine (structural XPath queries against the AST).
生态系统: 此技能属于包含3个技能的代码分析器套件 —(扫描与结果)·dx-code-analyzer-run(设置、配置、CI/CD)·dx-code-analyzer-configure(自定义规则编写)。dx-code-analyzer-custom-rule-create
当用户需要创建自定义规则以强制执行代码分析器内置规则未覆盖的模式时,使用此技能。支持Regex引擎(文本模式匹配)和PMD引擎(针对AST的结构化XPath查询)。
When This Skill Owns the Task
此技能负责的任务场景
Use when the work involves:
dx-code-analyzer-custom-rule-create- Creating a new custom rule for Code Analyzer (any engine)
- Enforcing team-specific coding standards via static analysis
- Banning specific patterns (System.debug, hardcoded IDs, TODOs)
- Writing XPath expressions for PMD rules (Apex or metadata XML)
- Writing regex patterns for the Regex engine
- Setting up custom ESLint rules/plugins for LWC/JavaScript
- Enforcing metadata governance (API versions, field descriptions, dangerous permissions)
- Overriding built-in rule thresholds (CyclomaticComplexity, ExcessiveParameterList, etc.)
- Organizing multiple rules into shared rulesets
- Iterating on a custom rule that isn't matching correctly
Delegate elsewhere when the user is:
- Running a scan against existing rules → skill
dx-code-analyzer-run - Configuring engines, prerequisites, CI/CD → skill
dx-code-analyzer-configure - Explaining what an existing built-in rule means → skill
dx-code-analyzer-run - Writing Apex code or tests → /
generating-apexskillsrunning-apex-tests
当工作涉及以下内容时,使用:
dx-code-analyzer-custom-rule-create- 为代码分析器创建新的自定义规则(任意引擎)
- 通过静态分析强制执行团队特定的编码标准
- 禁用特定模式(System.debug、硬编码ID、TODO注释)
- 为PMD规则编写XPath表达式(Apex或元数据XML)
- 为Regex引擎编写正则表达式模式
- 为LWC/JavaScript设置自定义ESLint规则/插件
- 强制执行元数据管控(API版本、字段描述、危险权限)
- 覆盖内置规则阈值(CyclomaticComplexity、ExcessiveParameterList等)
- 将多个规则组织到共享规则集中
- 迭代调整匹配不正确的自定义规则
当用户有以下需求时,转交至其他技能:
- 根据现有规则运行扫描 → 技能
dx-code-analyzer-run - 配置引擎、前置条件、CI/CD → 技能
dx-code-analyzer-configure - 解释现有内置规则的含义 → 技能
dx-code-analyzer-run - 编写Apex代码或测试 → /
generating-apex技能running-apex-tests
Required Context to Gather First
首先需要收集的必要上下文
Ask for or infer:
- What pattern to catch — what code should be flagged? (If user selected code in their IDE, the selection IS the answer — do not re-ask.)
- What to allow — any exceptions? (test classes, specific contexts)
- File scope — which file types? (.cls, .trigger, .js, all?)
- Severity — how critical? (default: 3/Moderate)
If the user selected code (IDE selection context present), treat it as the pattern definition. Skip clarification unless genuinely ambiguous about what aspect of the selection to target.
If the request is vague with NO selection ("add a rule for best practices"), ask ONE clarifying question:
"What specific pattern should this rule flag?"
询问或推断以下信息:
- 需要捕获的模式 — 哪些代码需要被标记?(如果用户在IDE中选中了代码,该选中内容即为答案,无需再次询问。)
- 允许的例外 — 是否有任何例外情况?(测试类、特定上下文)
- 文件范围 — 针对哪些文件类型?(.cls、.trigger、.js,或全部?)
- 严重程度 — 优先级如何?(默认:3/中等)
如果用户选中了代码(存在IDE选中上下文),将其视为模式定义。除非对选中内容的目标方面确实存在歧义,否则无需澄清。
如果请求模糊且无选中内容(例如“添加最佳实践规则”),仅询问一个澄清问题:
"此规则应标记哪些特定模式?"
Hard Constraints
硬性约束
These are non-negotiable rules. Violating any of them is a skill failure regardless of whether the output happens to work.
-
ALWAYS runbefore writing XPath. No exceptions. Do not use node names from memory, references, or prior conversations. The AST is the source of truth — run
ast-dump, read the output, then write XPath that matches what you see. Even for "well-known" patterns like SOQL-in-loop, run ast-dump first. If you skip this step and the rule works, it is still a process failure.sf code-analyzer ast-dump -
ALWAYS use the scripts to create rules. For regex rules, ALWAYS use. For PMD rules, ALWAYS use
create-regex-rule.js. Do NOT manually editcreate-pmd-rule.jsto add rule definitions — regex patterns in YAML cause escaping failures (quotes inside quotes, backslashes getting eaten). The scripts handle YAML serialization correctly every time.code-analyzer.yml -
NEVER manually editafter a script writes to it — even to fix a bad value. The scripts produce correctly-escaped YAML. If you then rewrite or restructure the file, you WILL break the escaping. If the user added top-level config (like
code-analyzer.yml), leave it alone too — only touch what you wrote.ignores.filesIf a script's output looks wrong (rule fails to validate, YAML parse error, stray characters in the regex):- DO NOT patch the YAML by hand. That is exactly the failure mode this constraint exists to prevent.
- Always delete the broken rule's entire YAML block, then re-invoke the script with corrected arguments. Removing a block you just wrote does not violate this rule; rewriting fields inside it does.
- If the script accepted bad input and produced bad output, the input was wrong (e.g., with a stray space — the flags must be
--regex "/.../ g"exactly, no whitespace). Re-invoke with the corrected argument./g - If you genuinely believe the script has a bug, STOP and surface it to the user. Do not hand-edit as a workaround.
-
must be
--regexwith NO whitespace. The script trims and validates flags strictly — only/pattern/flags,g,i,m,s,u.y(with a space) is rejected; so is/pat/ g(invalid flag) and/pat/x(no flags). The global flag/pat/is mandatory. If validation fails, fix the argument — do NOT bypass by writing YAML directly.g -
ALWAYS validate after creation. Runbefore testing. If
sf code-analyzer rules --rule-selector <engine>:<name>, the YAML didn't parse — delete the block, fix the argument, re-invoke the script.Found 0 rules -
ALWAYS test against a sample file. Confirm at least one true positive and one true negative.For regex rules, the negative sample MUST NOT contain the pattern text anywhere — including inside comments and string literals. Regex engines scan raw text;IS a match for
// no System.debug here. Trace your pattern against the negative file mentally before running it./System\.debug/g -
Create rules ONE AT A TIME, sequentially. When the user requests multiple rules, create each rule individually through the full workflow (create → validate → test positive → test negative) before starting the next one. Do NOT batch-create rules — if one fails, it corrupts the config for all subsequent rules. Complete each rule end-to-end, confirm it works, then move to the next.
-
For regex rules, exclude test classes via—
ignores.filesdoes NOT do this.regex_ignoreis a per-LINE filter (the line must match BOTH the rule and the ignore pattern); it cannot exclude an entire test class. If the user's intent is "skip test classes," add a top-levelregex_ignoreblock with globs likeignores.filesAFTER all rules are created — do not interleave config edits with script invocations."**/*Test.cls"
这些是不可协商的规则。违反任何一条都属于技能执行失败,无论输出是否碰巧可用。
-
编写XPath前必须运行。无例外情况。不要凭记忆、参考资料或之前的对话使用节点名称。AST是唯一可信来源 — 运行
ast-dump,读取输出,然后编写与输出匹配的XPath。即使是“众所周知”的模式(如循环内的SOQL),也要先运行ast-dump。如果跳过此步骤但规则生效,仍属于流程失败。sf code-analyzer ast-dump -
必须使用脚本创建规则。对于Regex规则,必须使用。对于PMD规则,必须使用
create-regex-rule.js。请勿手动编辑create-pmd-rule.js添加规则定义 — YAML中的正则表达式会导致转义失败(引号嵌套、反斜杠丢失)。脚本每次都能正确处理YAML序列化。code-analyzer.yml -
脚本写入后切勿手动编辑— 即使是修复错误值也不行。脚本会生成正确转义的YAML。如果之后重写或重构文件,肯定会破坏转义。如果用户添加了顶层配置(如
code-analyzer.yml),请勿修改 — 只改动你编写的内容。ignores.files如果脚本输出看起来有误(规则验证失败、YAML解析错误、正则表达式中存在多余字符):- 请勿手动修补YAML。这正是此约束要避免的失败场景。
- 始终删除错误规则的整个YAML块,然后使用修正后的参数重新调用脚本。删除刚编写的块不属于违反此规则;重写块内的字段才是。
- 如果脚本接受了错误输入并生成错误输出,问题出在输入上(例如包含多余空格 — 标志必须严格为
--regex "/.../ g",无空格)。使用修正后的参数重新调用。/g - 如果确实认为脚本存在bug,请停止操作并告知用户。请勿手动编辑作为变通方案。
-
必须为
--regex格式,且无空格。脚本会严格修剪并验证标志 — 仅允许/pattern/flags、g、i、m、s、u。y(带空格)会被拒绝;/pat/ g(无效标志)和/pat/x(无标志)也会被拒绝。全局标志/pat/是必填项。如果验证失败,请修正参数 — 请勿直接编写YAML绕过验证。g -
创建后必须验证。在测试前运行。如果显示
sf code-analyzer rules --rule-selector <engine>:<name>,说明YAML未解析 — 删除块,修正参数,重新调用脚本。Found 0 rules -
必须针对示例文件测试。确认至少一个真阳性和一个真阴性结果。对于Regex规则,阴性示例绝对不能包含任何模式文本 — 包括注释和字符串字面量内的文本。Regex引擎会扫描原始文本;会匹配
// no System.debug here。运行前先在脑海中对照阴性文件检查你的模式。/System\.debug/g -
一次只创建一个规则,按顺序执行。当用户请求多个规则时,在开始下一个规则前,完成每个规则的完整工作流程(创建→验证→阳性测试→阴性测试)。请勿批量创建规则 — 如果一个规则失败,会破坏后续所有规则的配置。完成每个规则的端到端流程,确认可用后再进行下一个。
-
对于Regex规则,通过排除测试类 —
ignores.files无法实现此功能。regex_ignore是逐行过滤器(该行必须同时匹配规则和忽略模式);它无法排除整个测试类。如果用户的意图是“跳过测试类”,在所有规则创建完成后,添加顶层regex_ignore块,使用类似ignores.files的通配符 — 请勿在脚本调用期间穿插配置编辑。"**/*Test.cls"
Engine Selection
引擎选择
| Pattern Type | Engine | Why |
|---|---|---|
| Text/string pattern (TODO, hardcoded ID, keyword) | Regex | Simple, fast, no Java needed |
| Apex code structure (method calls, nesting, SOQL in loops) | PMD/XPath (language=apex) | Understands AST, not fooled by comments/strings |
| Metadata XML governance (API version, permissions, descriptions) | PMD/XPath (language=xml) | Structural XML matching with namespace handling |
| LWC/JavaScript/TypeScript patterns | ESLint* | Standard JS tooling, plugin ecosystem |
| Both could work (Apex/metadata only) | Regex first | Simpler to create and maintain |
* For ESLint: ALWAYS check Tier 1 (built-in rules) and Tier 2 (configurable rules) BEFORE creating a custom plugin. See .
references/eslint-rules-discovery.md⚠️ "Both could work → Regex first" NEVER applies to JavaScript/LWC/TypeScript files. JS/LWC/TS patterns MUST use ESLint — Regex cannot distinguish code from comments/strings in JS and produces false positives. Do NOT rationalize Regex for JS files based on "simplicity" or "no npm dependencies."
Tell the user which engine you chose and why. Respect their preference if they disagree.
| 模式类型 | 引擎 | 原因 |
|---|---|---|
| 文本/字符串模式(TODO、硬编码ID、关键字) | Regex | 简单、快速,无需Java |
| Apex代码结构(方法调用、嵌套、循环内的SOQL) | PMD/XPath(language=apex) | 理解AST,不会被注释/字符串误导 |
| 元数据XML管控(API版本、权限、描述) | PMD/XPath(language=xml) | 结构化XML匹配,支持命名空间处理 |
| LWC/JavaScript/TypeScript模式 | ESLint* | 标准JS工具,插件生态丰富 |
| 两种引擎都适用(仅Apex/元数据) | 优先使用Regex | 创建和维护更简单 |
* 对于ESLint: 在创建自定义插件前,必须先检查Tier 1(内置规则)和Tier 2(可配置规则)。详见。
references/eslint-rules-discovery.md⚠️ “两种引擎都适用→优先Regex”绝不适用于JavaScript/LWC/TypeScript文件。JS/LWC/TS模式必须使用ESLint — Regex无法区分JS中的代码与注释/字符串,会产生误报。请勿以“简单”或“无npm依赖”为由为JS文件使用Regex。
告知用户你选择的引擎及原因。如果用户有不同偏好,请尊重其选择。
Excluding Test Classes — Strategy by Engine
排除测试类 — 按引擎划分的策略
When a rule should NOT apply to test classes, the approach differs by engine:
| Engine | How to exclude test classes | Notes |
|---|---|---|
| PMD (Apex) | Add | Structural exclusion — works perfectly, no config changes needed |
| Regex | Use | |
| ESLint | Use | Standard ESLint file-level ignores |
⚠️ is NOT file-level exclusion. It only skips matches on lines that ALSO match the ignore pattern. Example: only suppresses violations on lines containing — a SOQL query on line 50 of a test class still flags because line 50 doesn't contain . To exclude test files from regex rules entirely, use:
regex_ignoreregex_ignore: "/@isTest/i"@isTest@isTestyaml
ignores:
files:
- "**/*Test.cls"
- "**/*_Test.cls"⚠️ is GLOBAL — it affects ALL engines and ALL rules. If you need test-class exclusion for some rules but not others (e.g., exclude tests from SOQL rules but still scan tests for @AuraEnabled), use PMD with XPath for the rules that need selective exclusion. PMD's XPath can structurally check per-method or per-class — Regex cannot.
ignores.files@Test = true()Decision guide for Apex rules that should skip test classes:
- If the pattern is structural (method calls, annotations, nesting) → use PMD. XPath handles test-class exclusion natively.
- If the pattern is purely textual AND all regex rules should skip tests → use Regex + .
ignores.files - If you have a mix (some rules skip tests, others don't) → use PMD for the test-sensitive rules, Regex for the others.
当规则不应应用于测试类时,不同引擎的处理方式不同:
| 引擎 | 排除测试类的方法 | 说明 |
|---|---|---|
| PMD (Apex) | 在XPath中添加 | 结构化排除 — 完全有效,无需修改配置 |
| Regex | 在 | |
| ESLint | 在 | 标准ESLint文件级忽略方式 |
⚠️ 不是文件级排除。它仅跳过同时匹配忽略模式的行上的匹配项。示例:仅抑制包含的行上的违规 — 测试类第50行的SOQL查询仍会被标记,因为第50行不包含。要从Regex规则中完全排除测试文件,请使用:
regex_ignoreregex_ignore: "/@isTest/i"@isTest@isTestyaml
ignores:
files:
- "**/*Test.cls"
- "**/*_Test.cls"⚠️ 是全局设置 — 它会影响所有引擎和所有规则。如果需要部分规则排除测试类,而其他规则不排除(例如,SOQL规则排除测试类,但仍扫描测试类中的@AuraEnabled),请对需要选择性排除的规则使用PMD + XPath。PMD的XPath可以按方法或类结构化检查 — Regex无法实现此功能。
ignores.files@Test = true()针对应跳过测试类的Apex规则的决策指南:
- 如果模式是结构化的(方法调用、注解、嵌套)→ 使用PMD。XPath原生支持测试类排除。
- 如果模式是纯文本且所有Regex规则都应跳过测试 → 使用Regex + 。
ignores.files - 如果存在混合需求(部分规则跳过测试,其他规则不跳过)→ 对测试敏感的规则使用PMD,其他规则使用Regex。
Workflow
工作流程
When User Selects Code (IDE Selection)
用户选中代码时(IDE选中场景)
When the user highlights a code block in their editor and asks to "catch this", "flag this pattern", "create a rule for this", or similar:
- The selection IS your positive sample. Do NOT ask "what pattern should this rule flag?" — the user already showed you. Do NOT write a new sample from scratch.
- Identify what's structural vs. incidental in the selection:
- Structural (rule-worthy): the method call, the loop pattern, the missing keyword, the nesting
- Incidental (ignore): specific variable names, string values, parameter counts
- Ask ONE question if ambiguous: "Should the rule catch all calls, or only those without a LoggingLevel parameter?"
System.debug
- Ast-dump the ACTUAL file the user has open (not a new sample file):
bash
sf code-analyzer ast-dump --file <the-open-file.cls> --output-file <ast.xml> - Find the selection in the AST output — locate the nodes corresponding to the highlighted lines. These are your target nodes.
- Generalize the XPath — write XPath that matches the structural pattern, NOT the specific instance. Replace specific variable names with wildcards, keep structural nodes and discriminating attributes.
- Continue with standard workflow (negative sample, create rule, validate, test positive + negative).
Example flow:
- User selects:
Database.query('SELECT Id FROM ' + objectName) - Structural pattern: call (dynamic SOQL)
Database.query - Incidental: the specific string concatenation inside
- Engine: PMD (structural call detection)
- XPath:
//MethodCallExpression[@FullMethodName='Database.query'] - NOT: regex matching (would miss multiline, match comments)
Database.query
Example flow (block selection):
- User selects a 5-line block with SOQL inside a for-each loop
- Structural: SOQL query as descendant of loop body
- Incidental: specific query fields, variable names
- Engine: PMD
- Ast-dump the open file → find ForEachStatement + SoqlExpression in body
- XPath:
//ForEachStatement/BlockStatement//SoqlExpression
当用户在编辑器中高亮代码块并要求“捕获此内容”、“标记此模式”、“为此创建规则”或类似请求时:
- 选中内容即为阳性样本。请勿询问“此规则应标记哪些模式?” — 用户已经展示给你了。请勿从头编写新样本。
- 识别选中内容中的结构化元素与偶然元素:
- 结构化元素(值得规则关注):方法调用、循环模式、缺失的关键字、嵌套结构
- 偶然元素(忽略):特定变量名、字符串值、参数数量
- 如果存在歧义,仅问一个问题:“规则应捕获所有调用,还是仅捕获没有LoggingLevel参数的调用?”
System.debug
- 对用户打开的实际文件执行ast-dump(不是新样本文件):
bash
sf code-analyzer ast-dump --file <the-open-file.cls> --output-file <ast.xml> - 在AST输出中找到选中内容 — 定位与高亮行对应的节点。这些是你的目标节点。
- 泛化XPath — 编写匹配结构化模式的XPath,而非特定实例。将特定变量名替换为通配符,保留结构化节点和区分属性。
- 继续执行标准工作流程(阴性样本、创建规则、验证、阳性+阴性测试)。
示例流程:
- 用户选中:
Database.query('SELECT Id FROM ' + objectName) - 结构化模式:调用(动态SOQL)
Database.query - 偶然元素:内部的特定字符串拼接
- 引擎:PMD(结构化调用检测)
- XPath:
//MethodCallExpression[@FullMethodName='Database.query'] - 错误做法:使用正则匹配(会遗漏多行调用,匹配注释)
Database.query
示例流程(块选中):
- 用户选中包含for-each循环内SOQL的5行代码块
- 结构化模式:循环体的后代节点中的SOQL查询
- 偶然元素:特定查询字段、变量名
- 引擎:PMD
- 对打开的文件执行ast-dump → 在body中找到ForEachStatement + SoqlExpression
- XPath:
//ForEachStatement/BlockStatement//SoqlExpression
For Regex Rules
针对Regex规则
- Write a positive sample (5-10 lines) demonstrating the violation. Write sample files inside the project workspace (e.g., a temporary directory at the project root) so Code Analyzer can target them.
samples/ - Write a SEPARATE negative sample file — code that looks similar but must NOT be flagged. Test your regex mentally against this file BEFORE creating the rule.
- Build and create the rule — read for the complete schema, then run the script:
references/regex-rule-schema.md⚠️ ALWAYS use the script. Do NOT manually write regex patterns intobashnode "<skill_dir>/scripts/create-regex-rule.js" \ --name "<RuleName>" --regex "<pattern>" --description "<desc>" \ --severity <1-5> --file-extensions ".cls,.trigger"— regex characters (quotes, backslashes, braces) inside YAML cause parsing failures. The script handles serialization correctly.code-analyzer.yml - Validate —
sf code-analyzer rules --rule-selector regex:<RuleName> - Test positive — — must find violations
sf code-analyzer run --rule-selector regex:<RuleName> --target <violation-sample> - Test negative — — must find 0 violations. If it flags clean code, your regex is too broad — go back and tighten the pattern.
sf code-analyzer run --rule-selector regex:<RuleName> --target <clean-sample> - Iterate if test fails (adjust regex, add , narrow extensions)
regex_ignore - Cleanup — delete ALL sample files you created. Do not leave temporary test fixtures in the user's project.
- 编写阳性样本(5-10行)展示违规情况。在项目工作区中编写样本文件(例如,项目根目录下的临时目录),以便代码分析器可以扫描到它们。
samples/ - 编写单独的阴性样本文件 — 看起来相似但绝对不能被标记的代码。在创建规则前,先在脑海中对照此文件测试你的正则表达式。
- 构建并创建规则 — 阅读获取完整 schema,然后运行脚本:
references/regex-rule-schema.md⚠️ 必须使用脚本。请勿手动将正则表达式写入bashnode "<skill_dir>/scripts/create-regex-rule.js" \ --name "<RuleName>" --regex "<pattern>" --description "<desc>" \ --severity <1-5> --file-extensions ".cls,.trigger"— YAML中的正则字符(引号、反斜杠、大括号)会导致解析失败。脚本会正确处理序列化。code-analyzer.yml - 验证 —
sf code-analyzer rules --rule-selector regex:<RuleName> - 阳性测试 — — 必须找到违规
sf code-analyzer run --rule-selector regex:<RuleName> --target <violation-sample> - 阴性测试 — — 必须找到0个违规。如果标记了干净代码,说明你的正则表达式范围太广 — 返回调整模式。
sf code-analyzer run --rule-selector regex:<RuleName> --target <clean-sample> - 迭代(如果测试失败,调整正则表达式、添加、缩小文件扩展名范围)
regex_ignore - 清理 — 删除你创建的所有样本文件。不要在用户项目中留下临时测试文件。
For PMD/XPath Rules (Apex)
针对PMD/XPath规则(Apex)
- Write a minimal sample (5-10 lines) demonstrating the violation. Write sample files inside the project workspace (e.g., a temporary directory at the project root) so Code Analyzer can target them. After both positive and negative tests pass, delete ALL sample files you created — both the original samples and any copies made during testing. Do not leave temporary test fixtures in the user's project. For loop-based rules, the positive sample MUST include all 3 Apex loop types (
samples/, traditionalfor-each, andfor) — omitting any loop type means the XPath won't be validated against it and may silently miss violations.while - ⚠️ MANDATORY: Dump the AST — — this step is NOT optional. Do NOT skip it even if you "already know" the node names. Run it, read the output, confirm the exact node names and attributes.
sf code-analyzer ast-dump --file <sample.cls> --output-file <ast.xml> - Read the AST output — identify the target node and its attributes from the ACTUAL ast-dump output (not from memory). Use and
references/apex-ast-reference.mdas supplementary context only.references/xpath-patterns.md - Write XPath — target the smallest stable node with discriminating attributes. Every node name in your XPath MUST appear verbatim in the ast-dump output you just read. Use (direct child) vs
/Childdeliberately — check the ast-dump to understand which nodes are siblings vs nested.//Descendant - ⚠️ BEFORE creating the rule: Write a SEPARATE negative sample file (5-10 lines) showing code that is CORRECT and must NOT be flagged. This MUST be a distinct file from the positive sample — do NOT combine positive and negative cases into one file. For loop-based rules, include idiom. Run
for (x : [SELECT...])on this negative sample file too. Read the output and trace your XPath against it — confirm it does NOT match any node in the negative AST. If it would match, go back to step 4 and tighten the XPath BEFORE proceeding. Do NOT skip this step or defer it until after rule creation. The negative file will be used again in step 9 for an explicit zero-violation confirmation.sf code-analyzer ast-dump - Create the rule — run the script:
bash
node "<skill_dir>/scripts/create-pmd-rule.js" \ --name "<RuleName>" --xpath "<expression>" --message "<msg>" \ --language apex --priority <1-5> - Validate —
sf code-analyzer rules --rule-selector pmd:<RuleName> - Test positive — — must find violations
sf code-analyzer run --rule-selector pmd:<RuleName> --target <violation-sample.cls> - Test negative — — must find 0 violations. If it flags clean code, your XPath is too broad — go back to step 4.
sf code-analyzer run --rule-selector pmd:<RuleName> --target <clean-sample.cls> - Iterate if test fails (re-examine AST, adjust XPath, check node names)
- Cleanup — delete ALL sample files you created (both positive and negative samples, and any ast-dump output files). Do not leave temporary test fixtures in the user's project.
- 编写最小样本(5-10行)展示违规情况。在项目工作区中编写样本文件(例如,项目根目录下的临时目录),以便代码分析器可以扫描到它们。阳性和阴性测试通过后,删除你创建的所有样本文件 — 包括原始样本和测试期间创建的任何副本。不要在用户项目中留下临时测试文件。对于基于循环的规则,阳性样本必须包含所有3种Apex循环类型(
samples/、传统for-each和for) — 遗漏任何一种循环类型意味着XPath不会针对其验证,可能会静默遗漏违规。while - ⚠️ 必须执行:导出AST — — 此步骤不可选。即使你“已经知道”节点名称,也请勿跳过。运行它,读取输出,确认确切的节点名称和属性。
sf code-analyzer ast-dump --file <sample.cls> --output-file <ast.xml> - 读取AST输出 — 从实际的ast-dump输出(而非记忆)中识别目标节点及其属性。仅将和
references/apex-ast-reference.md作为补充参考。references/xpath-patterns.md - 编写XPath — 定位具有区分属性的最小稳定节点。XPath中的每个节点名称必须与你刚读取的ast-dump输出完全一致。有意使用(直接子节点)与
/Child(后代节点) — 查看ast-dump以了解哪些节点是兄弟节点,哪些是嵌套节点。//Descendant - ⚠️ 创建规则前:编写单独的阴性样本文件(5-10行)展示正确且不能被标记的代码。此文件必须与阳性样本分开 — 请勿将阳性和阴性情况合并到一个文件中。对于基于循环的规则,包含写法。对阴性样本文件也运行
for (x : [SELECT...])。读取输出并对照它跟踪你的XPath — 确认它不会匹配阴性AST中的任何节点。如果会匹配,返回步骤4并在继续前收紧XPath。请勿跳过此步骤或推迟到规则创建后。阴性文件将在步骤9中用于明确确认零违规。sf code-analyzer ast-dump - 创建规则 — 运行脚本:
bash
node "<skill_dir>/scripts/create-pmd-rule.js" \ --name "<RuleName>" --xpath "<expression>" --message "<msg>" \ --language apex --priority <1-5> - 验证 —
sf code-analyzer rules --rule-selector pmd:<RuleName> - 阳性测试 — — 必须找到违规
sf code-analyzer run --rule-selector pmd:<RuleName> --target <violation-sample.cls> - 阴性测试 — — 必须找到0个违规。如果标记了干净代码,说明你的XPath范围太广 — 返回步骤4。
sf code-analyzer run --rule-selector pmd:<RuleName> --target <clean-sample.cls> - 迭代(如果测试失败,重新检查AST、调整XPath、检查节点名称)
- 清理 — 删除你创建的所有样本文件(阳性和阴性样本,以及任何ast-dump输出文件)。不要在用户项目中留下临时测试文件。
For PMD/XPath Rules (Metadata XML)
针对PMD/XPath规则(元数据XML)
- Identify the metadata file type (field, permissionset, profile, flow, etc.)
- Dump the XML AST — . If ast-dump fails with an error (e.g.,
sf code-analyzer ast-dump --file <file>-meta.xml --language xml --output-file <ast.xml>), fall back to reading the raw XML file directly — the XML DOM structure IS the AST for metadata files (what you see in the file is what PMD sees). Read the file, note element names, nesting, and text content."XmlEncoding is not a valid XML name" - Read the DOM structure — confirm element names, nesting, and text content from the ast-dump output OR the raw file. Use as supplementary context only.
references/metadata-xml-rules.md - Write XPath for PMD 7 — CRITICAL rules for metadata XML XPath:
- All element matching MUST use (namespace blocks bare names)
local-name()='ElementName' - Text content matching MUST use attribute (NOT
@Text— thetext()function does not work in PMD 7's XML language). Example:text()//*[@Text='ModifyAllData'] - Navigate from text nodes UP to parent elements using (text node → element → parent element)
../.. - Check sibling conditions via on the parent
.//*[@Text='value'] - See for the complete PMD 7 XPath pattern
references/metadata-xml-rules.md
- All element matching MUST use
- Configure file extensions — PMD's XML language only processes by default. Salesforce metadata files use compound extensions (
.xml,.permissionset-meta.xml, etc.) but.field-meta.xmlreturnspath.extname()from these, so.xmlis sufficient:.xml⚠️ Do NOT add compound extensions likeyamlengines: pmd: file_extensions: xml: [".xml"]— Code Analyzer's validator rejects them (.permissionset-meta.xmlpattern). Just/^[.][a-zA-Z0-9]+$/covers all Salesforce metadata files automatically..xml - Write a SEPARATE negative sample file — same as Apex rules: create a metadata file that is correct and must NOT be flagged. Verify the XPath does not match it BEFORE creating the rule. Both positive and negative samples should be extension files in the workspace so PMD can scan them directly.
.xml - Create the rule — run the script:
bash
node "<skill_dir>/scripts/create-pmd-rule.js" \ --name "<RuleName>" --xpath "<expression>" --message "<msg>" \ --language xml --priority <1-5> - Validate —
sf code-analyzer rules --rule-selector pmd:<RuleName> - Test positive — — must find violations
sf code-analyzer run --rule-selector pmd:<RuleName> --target <violation-sample>.xml - Test negative — — must find 0 violations
sf code-analyzer run --rule-selector pmd:<RuleName> --target <clean-sample>.xml - Iterate if test fails (check vs
@Text, verifytext()usage, check file extensions config)local-name() - Cleanup — delete ALL sample files you created (both positive and negative samples, and any copies made for testing). Do not leave temporary test fixtures in the user's project.
.xml
- 识别元数据文件类型(字段、权限集、配置文件、流等)
- 导出XML AST — 。如果ast-dump失败并报错(例如
sf code-analyzer ast-dump --file <file>-meta.xml --language xml --output-file <ast.xml>),回退到直接读取原始XML文件 — 对于元数据文件,XML DOM结构就是AST(文件中的内容就是PMD看到的内容)。读取文件,记录元素名称、嵌套结构和文本内容。"XmlEncoding is not a valid XML name" - 读取DOM结构 — 从ast-dump输出或原始文件中确认元素名称、嵌套结构和文本内容。仅将作为补充参考。
references/metadata-xml-rules.md - 为PMD 7编写XPath — 元数据XML XPath的关键规则:
- 所有元素匹配必须使用(命名空间会阻止裸名称匹配)
local-name()='ElementName' - 文本内容匹配必须使用属性(不能使用
@Text—text()函数在PMD 7的XML语言中不起作用)。示例:text()//*[@Text='ModifyAllData'] - 使用从文本节点向上导航到父元素(文本节点→元素→父元素)
../.. - 通过父元素的检查兄弟条件
.//*[@Text='value'] - 完整的PMD 7 XPath模式详见
references/metadata-xml-rules.md
- 所有元素匹配必须使用
- 配置文件扩展名 — PMD的XML语言默认仅处理文件。Salesforce元数据文件使用复合扩展名(
.xml、.permissionset-meta.xml等),但.field-meta.xml会从这些文件中返回path.extname(),因此.xml已足够:.xml⚠️ 请勿添加yamlengines: pmd: file_extensions: xml: [".xml"]这类复合扩展名 — 代码分析器的验证器会拒绝它们(匹配.permissionset-meta.xml模式)。仅/^[.][a-zA-Z0-9]+$/就会自动覆盖所有Salesforce元数据文件。.xml - 编写单独的阴性样本文件 — 与Apex规则相同:创建一个正确且不能被标记的元数据文件。在创建规则前验证XPath不会匹配它。阳性和阴性样本都应该是工作区中的扩展名文件,以便PMD可以直接扫描它们。
.xml - 创建规则 — 运行脚本:
bash
node "<skill_dir>/scripts/create-pmd-rule.js" \ --name "<RuleName>" --xpath "<expression>" --message "<msg>" \ --language xml --priority <1-5> - 验证 —
sf code-analyzer rules --rule-selector pmd:<RuleName> - 阳性测试 — — 必须找到违规
sf code-analyzer run --rule-selector pmd:<RuleName> --target <violation-sample>.xml - 阴性测试 — — 必须找到0个违规
sf code-analyzer run --rule-selector pmd:<RuleName> --target <clean-sample>.xml - 迭代(如果测试失败,检查与
@Text的使用、验证text()的使用、检查文件扩展名配置)local-name() - 清理 — 删除你创建的所有样本文件(阳性和阴性样本,以及任何用于测试的副本)。不要在用户项目中留下临时测试文件。
.xml
For ESLint Rules (LWC/JavaScript/TypeScript)
针对ESLint规则(LWC/JavaScript/TypeScript)
ESLint Discovery Workflow (Read First)
ESLint发现工作流程(先阅读)
ESLint has 200+ built-in rules plus thousands more from plugins. DO NOT attempt to create a custom plugin before checking if a built-in rule exists. The discovery workflow is:
-
Tier 1 (Built-In Rules) — 70% of requests
- Run:
sf code-analyzer rules --rule-selector eslint - Search for keywords (e.g., "console", "unused", "equal")
- Check LWC plugin rules ()
@lwc/lwc/* - If found: Configure and STOP
- Run:
-
Tier 2 (Configurable Rules) — 20% of requests
- Pattern is "ban function X"? →
no-restricted-globals - Pattern is "ban syntax Y"? →
no-restricted-syntax - Pattern is "ban property Z"? →
no-restricted-properties - If applicable: Configure and STOP
- Pattern is "ban function X"? →
-
Tier 3 (Custom Plugins) — 10% of requests
- Only for domain-specific multi-node patterns
- Requires Node.js code, testing, meta.docs metadata
- See:
references/eslint-custom-plugins.md
See: for complete discovery guide with examples.
references/eslint-rules-discovery.md-
⚠️ MANDATORY: Run the ESLint discovery workflow FIRST. 90% of ESLint requests are solved by built-in rules (Tier 1) or configurable rules like(Tier 2). Creating a custom plugin (Tier 3) is a LAST RESORT. Before proceeding:
no-restricted-syntaxa) Run:b) Search the output for keywords from the user's request (e.g., "console", "equal", "unused") c) Check LWC plugin rules: grep forsf code-analyzer rules --rule-selector eslintin the output d) If found: Configure it (see@lwc/lwc/) and STOP. Do NOT create a custom plugin. e) If not found: Check ifreferences/eslint-rules-discovery.md,no-restricted-globals, orno-restricted-syntaxcan express the pattern (Tier 2). f) Only if no Tier 1 or Tier 2 solution exists: Proceed to custom plugin creation.no-restricted-propertiesValidation: After configuration, runto confirm it appears. If it doesn't, the config is wrong.sf code-analyzer rules --rule-selector eslint:<ruleName>⚠️ Skipping this discovery workflow and creating a custom plugin when a built-in rule exists is a skill failure, regardless of whether the custom plugin works.
⚠️ Built-in ESLint rules vs. configurable ESLint rules: Code Analyzer bundles a SUBSET of ESLint rules in its base config. Rules like , , and are core ESLint rules but are NOT active until you enable them in an . They WILL appear in output ONLY after you configure them. Always validate (step 4) to confirm the rule actually loaded — do NOT assume a rule exists just because it's a core ESLint rule.
no-restricted-globalsno-restricted-syntaxno-restricted-propertieseslint.config.jssf code-analyzer rules- Install the ESLint plugin (skip if using a built-in/core ESLint rule) —
npm install --save-dev eslint-plugin-<name> - Create/update — add plugin and rule configuration (or just enable the built-in rule with
eslint.config.jsseverity). The file MUST exist before configuring"error"inengines.eslint.eslint_config_file— Code Analyzer validates the path and fails if the file is missing.code-analyzer.yml - Configure Code Analyzer — set in
engines.eslint.eslint_config_file. Do this AFTER the file exists.code-analyzer.yml - Validate — . If the rule does NOT appear, the config is wrong — do NOT proceed to testing. Check: (a) Is the
sf code-analyzer rules --rule-selector eslint:<ruleName>file in the correct location? (b) Does the plugin haveeslint.config.jsandmeta.docs.description? (c) Is the rule deprecated? Code Analyzer silently excludes deprecated rules.meta.docs.url - Write a test sample file in the workspace (e.g., ) demonstrating the violation
lwc/testSample/testSample.js - Test positive — — must find violations
sf code-analyzer run --rule-selector eslint:<ruleName> --target <test-sample> - Test negative — run against existing clean LWC files — must find 0 violations
- Cleanup — delete ALL sample files AND their parent directories (LWC requires a folder per component). Use , not just
rm -rf <directory>. Do not leave empty directories or temporary test fixtures in the user's project.rm <file> - See for complete guide
references/eslint-custom-plugins.md
ESLint有200+内置规则,加上插件提供的数千条规则。在检查是否存在内置规则前,请勿尝试创建自定义插件。发现工作流程如下:
-
Tier 1(内置规则) — 70%的请求
- 运行:
sf code-analyzer rules --rule-selector eslint - 搜索关键字(例如“console”、“unused”、“equal”)
- 检查LWC插件规则()
@lwc/lwc/* - 如果找到:配置规则并停止操作
- 运行:
-
Tier 2(可配置规则) — 20%的请求
- 模式是“禁用函数X”?→ 使用
no-restricted-globals - 模式是“禁用语法Y”?→ 使用
no-restricted-syntax - 模式是“禁用属性Z”?→ 使用
no-restricted-properties - 如果适用:配置规则并停止操作
- 模式是“禁用函数X”?→ 使用
-
Tier 3(自定义插件) — 10%的请求
- 仅适用于特定领域的多节点模式
- 需要Node.js代码、测试、meta.docs元数据
- 详见:
references/eslint-custom-plugins.md
详见: 获取完整的发现指南及示例。
references/eslint-rules-discovery.md-
⚠️ 必须执行:先运行ESLint发现工作流程。90%的ESLint请求可以通过内置规则(Tier 1)或这类可配置规则(Tier 2)解决。创建自定义插件(Tier 3)是最后的手段。在继续前:
no-restricted-syntaxa) 运行:b) 搜索输出中与用户请求相关的关键字(例如“console”、“equal”、“unused”) c) 检查LWC插件规则: 在输出中搜索sf code-analyzer rules --rule-selector eslintd) 如果找到: 配置规则(详见@lwc/lwc/)并停止操作。请勿创建自定义插件。 e) 如果未找到: 检查references/eslint-rules-discovery.md、no-restricted-globals或no-restricted-syntax是否可以表达该模式(Tier 2)。 f) 仅当Tier 1或Tier 2解决方案不存在时: 继续创建自定义插件。no-restricted-properties验证: 配置后,运行确认规则已加载。如果未加载,说明配置有误。sf code-analyzer rules --rule-selector eslint:<ruleName>⚠️ 跳过此发现工作流程并在存在内置规则时创建自定义插件属于技能执行失败,无论自定义插件是否可用。
⚠️ 内置ESLint规则与可配置ESLint规则的区别: 代码分析器在基础配置中捆绑了ESLint规则的一个子集。、和这类规则是ESLint核心规则,但在中启用前不会生效。只有在配置后,它们才会出现在输出中。始终验证(步骤4)以确认规则确实已加载 — 不要仅因为是ESLint核心规则就假设它存在。
no-restricted-globalsno-restricted-syntaxno-restricted-propertieseslint.config.jssf code-analyzer rules- 安装ESLint插件(如果使用内置/核心ESLint规则则跳过) —
npm install --save-dev eslint-plugin-<name> - 创建/更新— 添加插件和规则配置(或仅使用
eslint.config.js严重程度启用内置规则)。该文件必须存在,然后才能在"error"中配置code-analyzer.yml— 代码分析器会验证路径,如果文件缺失则失败。engines.eslint.eslint_config_file - 配置代码分析器 — 在中设置
code-analyzer.yml。必须在文件存在后执行此操作。engines.eslint.eslint_config_file - 验证 — 。如果规则未出现,说明配置有误 — 请勿继续测试。检查:(a)
sf code-analyzer rules --rule-selector eslint:<ruleName>文件是否在正确位置?(b) 插件是否有eslint.config.js和meta.docs.description?(c) 规则是否已弃用?代码分析器会静默排除已弃用的规则。meta.docs.url - 在工作区中编写测试样本文件(例如)展示违规情况
lwc/testSample/testSample.js - 阳性测试 — — 必须找到违规
sf code-analyzer run --rule-selector eslint:<ruleName> --target <test-sample> - 阴性测试 — 针对现有干净的LWC文件运行 — 必须找到0个违规
- 清理 — 删除所有样本文件及其父目录(LWC要求每个组件对应一个文件夹)。使用,不要仅删除文件。不要在用户项目中留下空目录或临时测试文件。
rm -rf <directory> - 完整指南详见
references/eslint-custom-plugins.md
Common ESLint patterns without a custom plugin
无需自定义插件的常见ESLint模式
For , , and config examples, see — "Banning APIs Without a Custom Plugin" section.
no-restricted-globalsno-restricted-syntaxno-restricted-properties<skill_dir>/references/eslint-custom-plugins.mdno-restricted-globalsno-restricted-syntaxno-restricted-properties<skill_dir>/references/eslint-custom-plugins.mdESLint Discovery Examples
ESLint发现示例
Example 1: Built-in rule (Tier 1)
- User: "Ban console.log in LWC"
- Discovery: → finds
sf code-analyzer rules --rule-selector eslint | grep consoleno-console - Action: Enable in eslint.config.js
no-console - Result: ✅ Done in 2 minutes (no custom plugin needed)
Example 2: Configurable rule (Tier 2)
- User: "Ban setTimeout in LWC"
- Discovery: No built-in rule
no-setTimeout - Action: Use with custom message
no-restricted-globals - Result: ✅ Done in 5 minutes (no custom plugin needed)
Example 3: LWC plugin rule (Tier 1)
- User: "Ban innerHTML for XSS prevention"
- Discovery: already exists
@lwc/lwc/no-inner-html - Action: Enable in config
@lwc/lwc/no-inner-html - Result: ✅ Done in 2 minutes (no custom plugin needed)
Example 4: Custom plugin justified (Tier 3)
- User: "Flag imperative Apex calls without error handling"
- Discovery: No built-in rule for this pattern
- Analysis: Pattern requires checking +
importwithout.then()— multi-node traversal.catch() - Action: Create custom plugin with visitor pattern
- Result: ✅ Custom plugin is justified (20+ minutes effort)
See for complete discovery workflow.
references/eslint-rules-discovery.md示例1:内置规则(Tier 1)
- 用户:“在LWC中禁用console.log”
- 发现:→ 找到
sf code-analyzer rules --rule-selector eslint | grep consoleno-console - 操作:在eslint.config.js中启用
no-console - 结果:✅ 2分钟完成(无需自定义插件)
示例2:可配置规则(Tier 2)
- 用户:“在LWC中禁用setTimeout”
- 发现:没有内置的规则
no-setTimeout - 操作:使用并添加自定义消息
no-restricted-globals - 结果:✅ 5分钟完成(无需自定义插件)
示例3:LWC插件规则(Tier 1)
- 用户:“禁用innerHTML以防止XSS”
- 发现:已存在
@lwc/lwc/no-inner-html - 操作:在配置中启用
@lwc/lwc/no-inner-html - 结果:✅ 2分钟完成(无需自定义插件)
示例4:合理创建自定义插件(Tier 3)
- 用户:“标记没有错误处理的命令式Apex调用”
- 发现:没有针对此模式的内置规则
- 分析:模式需要检查+
import但没有.then()— 多节点遍历.catch() - 操作:使用访问者模式创建自定义插件
- 结果:✅ 自定义插件合理(耗时20+分钟)
完整的发现工作流程详见。
references/eslint-rules-discovery.mdOverriding Built-in Rule Thresholds
覆盖内置规则阈值
To customize severity or properties on existing rules without writing new ones:
- Create a custom ruleset referencing the built-in rule with overrides
- Add to config — in
engines.pmd.custom_rulesetscode-analyzer.yml - See for override syntax and common examples
references/advanced-pmd-patterns.md
要在不编写新规则的情况下自定义现有规则的严重程度或属性:
- 创建引用内置规则并包含覆盖设置的自定义规则集
- 添加到配置 — 在中设置
code-analyzer.ymlengines.pmd.custom_rulesets - 覆盖语法和常见示例详见
references/advanced-pmd-patterns.md
Multi-Rule Requests
多规则请求
When the user asks for multiple rules at once (e.g., "create 5 rules for AppExchange review"), follow this protocol:
当用户同时请求多个规则时(例如“为AppExchange审核创建5条规则”),遵循以下流程:
Step 1: Plan the engine assignments FIRST
步骤1:先规划引擎分配
Before creating any rules, list ALL requested rules with their engine assignments. Present this plan to the user:
text
Rule plan:
1. RequireUserMode → PMD/XPath (needs test-class exclusion via AST)
2. NoHardcodedIds → Regex (text pattern, no structural context needed)
3. AuraEnabledCacheable → PMD/XPath (needs annotation + DML structural check)
4. CustomFieldDescription → PMD/XML (metadata governance)
5. NoSetTimeout → ESLint (JavaScript pattern)Key decision factors for engine assignment:
- Does the rule need to exclude test classes selectively? → PMD (XPath can check )
@Test = true() - Is it a pure text pattern with no structural context? → Regex
- Does it need to understand code structure (annotations, nesting, DML)? → PMD
- Is it JavaScript/LWC? → ESLint (never Regex)
- Is it metadata XML? → PMD with
language="xml"
在创建任何规则前,列出所有请求的规则及其引擎分配。将此计划呈现给用户:
text
规则计划:
1. RequireUserMode → PMD/XPath(需要通过AST排除测试类)
2. NoHardcodedIds → Regex(文本模式,无需结构上下文)
3. AuraEnabledCacheable → PMD/XPath(需要注解+DML结构检查)
4. CustomFieldDescription → PMD/XML(元数据管控)
5. NoSetTimeout → ESLint(JavaScript模式)引擎分配的关键决策因素:
- 规则是否需要选择性排除测试类?→ PMD(XPath可以检查)
@Test = true() - 是否为纯文本模式,无需结构上下文?→ Regex
- 是否需要理解代码结构(注解、嵌套、DML)?→ PMD
- 是否为JavaScript/LWC?→ ESLint(绝不使用Regex)
- 是否为元数据XML?→ 使用的PMD
language="xml"
Step 2: Create rules ONE AT A TIME, sequentially
步骤2:一次创建一个规则,按顺序执行
Create each rule through its full workflow (create → validate → test positive → test negative → confirm working) before starting the next one. Do NOT batch-create rules — if one fails, it corrupts the config for all subsequent rules.
Order of creation:
- Regex rules first (fastest, fewest dependencies)
- PMD Apex rules (require ast-dump per rule)
- PMD XML rules (may share a single ruleset file)
- ESLint rules last (require npm/config setup)
在开始下一个规则前,完成每个规则的完整工作流程(创建→验证→阳性测试→阴性测试→确认可用)。请勿批量创建规则 — 如果一个规则失败,会破坏后续所有规则的配置。
创建顺序:
- 先创建Regex规则(最快,依赖最少)
- 然后创建PMD Apex规则(每个规则需要ast-dump)
- 接着创建PMD XML规则(可共享单个规则集文件)
- 最后创建ESLint规则(需要npm/配置设置)
Step 3: Multiple PMD rules can share ONE ruleset file
步骤3:多个PMD规则可共享一个规则集文件
When creating multiple PMD rules, use the script for the first rule (it creates the ruleset XML file). For subsequent PMD rules going into the SAME ruleset file, you may add them manually to the existing XML file — this is the ONE exception to the "never edit manually" rule. The script always creates a new file; adding rules to an existing file requires editing the XML directly.
create-pmd-rule.js创建多个PMD规则时,对第一个规则使用脚本(它会创建规则集XML文件)。对于要添加到同一规则集文件的后续PMD规则,可以手动将它们添加到现有XML文件中 — 这是“绝不手动编辑”规则的唯一例外。脚本始终会创建新文件;向现有文件添加规则需要直接编辑XML。
create-pmd-rule.jsWhat NOT to do
禁止操作
- ❌ Do NOT rewrite the entire to reorganize it
code-analyzer.yml - ❌ Do NOT create all rules in parallel then validate all at once
- ❌ Do NOT create a PMD rule with an unverified XPath from the reference docs — ast-dump each pattern
- ❌ Do NOT mix engine types in one creation step (e.g., creating regex + PMD rules simultaneously)
- ❌ Do NOT add to
engines.eslint.eslint_config_filebefore the file existscode-analyzer.yml
- ❌ 请勿重写整个以重新组织内容
code-analyzer.yml - ❌ 请勿并行创建所有规则,然后一次性验证
- ❌ 请勿使用参考文档中未经验证的XPath创建PMD规则 — 每个模式都要执行ast-dump
- ❌ 请勿在一个创建步骤中混合引擎类型(例如同时创建Regex + PMD规则)
- ❌ 在文件存在前,请勿将添加到
engines.eslint.eslint_config_filecode-analyzer.yml
High-Signal Rules
高信号规则
| Rule | Rationale |
|---|---|
Rule names must match | Code Analyzer validation rejects others |
Regex must be | JavaScript regex literal notation required |
File extensions must start with | Validation enforces |
| Always validate after creation | |
| Always test against sample code | Catches XPath/regex mismatches before full scan |
Use | More reliable than |
⚠️ NEVER skip | Run |
PMD 7 boolean attributes: use | In PMD 7, boolean attributes like |
| Auto-discovered by CLI — placing it elsewhere causes silent failures for rule authors |
XML rules MUST use | Salesforce metadata namespace breaks bare element names |
XML text matching MUST use | |
| |
XML rules need | PMD only scans |
Named capture groups | Narrows the violation highlight to just the captured portion |
Salesforce IDs start with | Use |
| It only skips lines where the ignore pattern matches. It does NOT exclude entire files or classes. A hardcoded ID on line 10 of a test class still flags unless that specific line contains the ignore pattern (e.g., |
| ALWAYS use scripts to create rules | Do NOT manually edit |
Override built-in rules via | Change thresholds without writing new rules |
| NEVER use Regex for JS/LWC/TS files | Regex cannot distinguish code from comments/strings in JS — always use ESLint for JavaScript patterns |
| Check built-in ESLint rules before writing custom ones | |
| 规则 | 理由 |
|---|---|
规则名称必须匹配 | 代码分析器验证会拒绝其他格式 |
正则表达式必须为 | 需要符合JavaScript正则字面量表示法 |
文件扩展名必须以 | 验证强制执行 |
| 创建后必须验证 | |
| 必须针对示例代码测试 | 在全面扫描前捕获XPath/正则表达式不匹配问题 |
在XPath中对方法调用使用 | 比单独使用 |
⚠️ 绝不跳过 | 运行 |
PMD 7布尔属性:使用 | 在PMD 7中, |
| CLI会自动发现 — 放在其他位置会导致规则作者遇到静默失败 |
XML规则必须使用 | Salesforce元数据命名空间会阻止裸元素名称匹配 |
XML文本匹配必须使用 | |
| |
XML规则需要 | PMD默认仅扫描 |
正则表达式中的命名捕获组 | 将违规高亮范围缩小到仅捕获的部分 |
Salesforce ID以 | 使用 |
| 它仅跳过匹配忽略模式的行。它不会排除整个文件或类。测试类第10行的硬编码ID仍会被标记,除非该行包含忽略模式(例如 |
| 必须使用脚本创建规则 | 请勿手动编辑 |
通过 | 无需编写新规则即可更改阈值 |
| 绝不为JS/LWC/TS文件使用Regex | Regex无法区分JS中的代码与注释/字符串 — 始终为JavaScript模式使用ESLint |
| 编写自定义规则前先检查内置ESLint规则 | |
Gotchas
常见陷阱
| Issue | Resolution |
|---|---|
| XPath written without running ast-dump | ALWAYS run ast-dump first. Even if the rule works, skipping ast-dump is a process failure. Node names change between PMD versions and are not guessable. |
SOQL-in-loop rule flags | Use |
| Used Regex for a JS/LWC/TS pattern | NEVER use Regex for JavaScript files. Regex cannot distinguish code from comments/strings in JS. Always use ESLint — check if a built-in rule (e.g., |
| XPath returns 0 matches (XML metadata) | Three common causes: (1) Forgot |
Regex rule written inline into | ALWAYS use |
| |
XPath | PMD 7 boolean attributes ( |
Loop-based rule only covers | Apex has 3 loop types: |
Rewrote | NEVER manually rewrite the file after a script runs. Add top-level config blocks (like |
| Multiple rules created at once — one failure breaks all subsequent rules | Create rules one at a time, sequentially. Complete the full workflow (create → validate → test) for each rule before starting the next. |
For additional diagnostics (wrong severity, Java not found, ESLint config path, metadata file type scoping, etc.) see .
<skill_dir>/references/troubleshooting.md| 问题 | 解决方案 |
|---|---|
| 未运行ast-dump就编写XPath | 必须先运行ast-dump。即使规则生效,跳过ast-dump也属于流程失败。PMD版本不同,节点名称会变化,无法猜测。 |
SOQL-in-loop规则标记 | 使用 |
| 为JS/LWC/TS模式使用Regex | 绝不为JavaScript文件使用Regex。Regex无法区分JS中的代码与注释/字符串。始终使用ESLint — 先检查是否存在内置规则(例如 |
| XPath返回0匹配(XML元数据) | 三个常见原因:(1) 忘记使用 |
将Regex规则直接写入 | 必须使用 |
| |
XPath | PMD 7的布尔属性( |
基于循环的规则仅覆盖 | Apex有3种循环类型: |
脚本运行后重写 | 脚本运行后切勿手动重写文件。仅添加顶层配置块(如 |
| 同时创建多个规则 — 一个失败破坏后续所有规则 | 一次创建一个规则,按顺序执行。完成每个规则的完整工作流程(创建→验证→测试)后再开始下一个。 |
其他诊断(错误的严重程度、未找到Java、ESLint配置路径、元数据文件类型范围等)详见。
<skill_dir>/references/troubleshooting.mdCross-Skill Integration
跨技能集成
| Need | Delegate to | Reason |
|---|---|---|
| Run a full scan after creating rule | | Scan execution and result presentation |
| Install Code Analyzer / fix prerequisites | | Setup and troubleshooting |
| Explain an existing built-in rule | | Rule description and docs lookup |
Edit | | Configuration management |
| 需求 | 转交至 | 原因 |
|---|---|---|
| 创建规则后运行全面扫描 | | 扫描执行和结果展示 |
| 安装代码分析器 / 修复前置条件 | | 设置和故障排除 |
| 解释现有内置规则 | | 规则描述和文档查询 |
编辑 | | 配置管理 |
Script Execution
脚本执行
<skill_dir>All scripts are bundled in the subdirectory of the same directory that contains this SKILL.md file. Use the absolute path to that directory — do NOT use as that resolves relative to the current working directory, not the skill directory.
scripts/./scripts/bash
node "<skill_dir>/scripts/create-regex-rule.js" \
--name "RuleName" --regex "/pattern/flags" ...⚠️ DO NOT:
- ❌ Invent or generate script code yourself
- ❌ Use bare relative paths like (won't resolve from user's CWD)
node scripts/create-regex-rule.js - ❌ Use heredocs or inline script content
- ❌ Skip resolving — find the absolute path first
<skill_dir>
<skill_dir>所有脚本都捆绑在包含此SKILL.md文件的目录的子目录中。使用该目录的绝对路径 — 请勿使用,因为它会相对于当前工作目录解析,而非技能目录。
scripts/./scripts/bash
node "<skill_dir>/scripts/create-regex-rule.js" \
--name "RuleName" --regex "/pattern/flags" ...⚠️ 禁止操作:
- ❌ 自行发明或生成脚本代码
- ❌ 使用这类裸相对路径(无法从用户的当前工作目录解析)
node scripts/create-regex-rule.js - ❌ 使用 heredocs 或内联脚本内容
- ❌ 跳过解析— 先找到绝对路径
<skill_dir>
Reference File Index
参考文件索引
| File | When to read |
|---|---|
| Building a regex rule — complete field reference, validation rules, multi-rule example |
| Writing XPath for Apex — index of pattern categories with syntax reference and AST node vocabulary |
| XPath patterns for SOQL/DML in loops, Database methods in loops |
| XPath patterns for banning methods and annotation patterns (@AuraEnabled, @future, @IsTest) |
| XPath patterns for sharing declarations, SOQL security, hardcoded IDs |
| XPath patterns for code structure, test quality, naming conventions |
| Reading Apex AST dumps — node hierarchy, modifier attributes, key node types |
| Writing rules for metadata XML — namespace workaround, common structures, XPath patterns |
| Multi-rule rulesets, overriding built-in rules, exclusion patterns, Java rules, sharing across projects |
| READ FIRST for ANY ESLint request — discovery workflow, built-in rules, Tier 1-3 index |
| ESLint Tier 2: no-restricted-globals, no-restricted-syntax, no-restricted-properties patterns |
| ESLint Tier 3: when to create custom plugins + complete examples for all tiers |
| Creating custom ESLint plugins — ONLY after discovery workflow confirms no built-in or configurable rule exists (Tier 3) |
| When validation or testing fails — error diagnosis by engine type |
| PMD XML skeleton with placeholders for the create-pmd-rule script |
| 6 real-world regex rules solving community-reported problems |
| 6 real-world XPath rules for Apex with AST context and step-by-step creation |
| Index of 6 real-world metadata XML rules (permissions, descriptions, API versions, flows) |
| Metadata examples: ModifyAllData/ViewAllData, field permissions in profiles |
| Metadata examples: custom field descriptions, minimum API version |
| Metadata examples: flow auto-layout, flow fault handlers |
| 文件 | 阅读时机 |
|---|---|
| 构建Regex规则时 — 完整字段参考、验证规则、多规则示例 |
| 为Apex编写XPath时 — 模式类别索引、语法参考和AST节点词汇表 |
| 针对循环内SOQL/DML、循环内Database方法的XPath模式 |
| 针对禁用方法和注解模式(@AuraEnabled、@future、@IsTest)的XPath模式 |
| 针对共享声明、SOQL安全、硬编码ID的XPath模式 |
| 针对代码结构、测试质量、命名规范的XPath模式 |
| 读取Apex AST导出时 — 节点层次结构、修饰符属性、关键节点类型 |
| 为元数据XML编写规则时 — 命名空间变通方案、常见结构、XPath模式 |
| 多规则规则集、覆盖内置规则、排除模式、Java规则、跨项目共享 |
| 任何ESLint请求都要先阅读 — 发现工作流程、内置规则、Tier 1-3索引 |
| ESLint Tier 2:no-restricted-globals、no-restricted-syntax、no-restricted-properties模式 |
| ESLint Tier 3:何时创建自定义插件 + 所有层级的完整示例 |
| 创建自定义ESLint插件时 — 仅在发现工作流程确认没有内置或可配置规则时使用(Tier 3) |
| 验证或测试失败时 — 按引擎类型进行错误诊断 |
| PMD XML骨架,包含create-pmd-rule脚本的占位符 |
| 6个解决社区报告问题的真实Regex规则 |
| 6个带AST上下文和分步创建过程的真实Apex XPath规则 |
| 6个真实元数据XML规则索引(权限、描述、API版本、流) |
| 元数据示例:ModifyAllData/ViewAllData、配置文件中的字段权限 |
| 元数据示例:自定义字段描述、最低API版本 |
| 元数据示例:流自动布局、流故障处理程序 |