Loading...
Loading...
Compare original and translation side by side
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
生态系统: 此技能属于包含3个技能的代码分析器套件 —(扫描与结果)·dx-code-analyzer-run(设置、配置、CI/CD)·dx-code-analyzer-configure(自定义规则编写)。dx-code-analyzer-custom-rule-create
dx-code-analyzer-custom-rule-createdx-code-analyzer-rundx-code-analyzer-configuredx-code-analyzer-rungenerating-apexrunning-apex-testsdx-code-analyzer-custom-rule-createdx-code-analyzer-rundx-code-analyzer-configuredx-code-analyzer-rungenerating-apexrunning-apex-tests"What specific pattern should this rule flag?"
"此规则应标记哪些特定模式?"
ast-dumpsf code-analyzer ast-dumpcreate-regex-rule.jscreate-pmd-rule.jscode-analyzer.ymlcode-analyzer.ymlignores.files--regex "/.../ g"/g--regex/pattern/flagsgimsuy/pat/ g/pat/x/pat/gsf code-analyzer rules --rule-selector <engine>:<name>Found 0 rules// no System.debug here/System\.debug/gignores.filesregex_ignoreregex_ignoreignores.files"**/*Test.cls"ast-dumpsf code-analyzer ast-dumpcreate-regex-rule.jscreate-pmd-rule.jscode-analyzer.ymlcode-analyzer.ymlignores.files--regex "/.../ g"/g--regex/pattern/flagsgimsuy/pat/ g/pat/x/pat/gsf code-analyzer rules --rule-selector <engine>:<name>Found 0 rules// no System.debug here/System\.debug/gignores.filesregex_ignoreregex_ignoreignores.files"**/*Test.cls"| 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 |
references/eslint-rules-discovery.md| 模式类型 | 引擎 | 原因 |
|---|---|---|
| 文本/字符串模式(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 | 创建和维护更简单 |
references/eslint-rules-discovery.md| 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 |
regex_ignoreregex_ignore: "/@isTest/i"@isTest@isTestignores:
files:
- "**/*Test.cls"
- "**/*_Test.cls"ignores.files@Test = true()ignores.files| 引擎 | 排除测试类的方法 | 说明 |
|---|---|---|
| PMD (Apex) | 在XPath中添加 | 结构化排除 — 完全有效,无需修改配置 |
| Regex | 在 | |
| ESLint | 在 | 标准ESLint文件级忽略方式 |
regex_ignoreregex_ignore: "/@isTest/i"@isTest@isTestignores:
files:
- "**/*Test.cls"
- "**/*_Test.cls"ignores.files@Test = true()ignores.filesSystem.debugsf code-analyzer ast-dump --file <the-open-file.cls> --output-file <ast.xml>Database.query('SELECT Id FROM ' + objectName)Database.query//MethodCallExpression[@FullMethodName='Database.query']Database.query//ForEachStatement/BlockStatement//SoqlExpressionSystem.debugsf code-analyzer ast-dump --file <the-open-file.cls> --output-file <ast.xml>Database.query('SELECT Id FROM ' + objectName)Database.query//MethodCallExpression[@FullMethodName='Database.query']Database.query//ForEachStatement/BlockStatement//SoqlExpressionsamples/references/regex-rule-schema.mdnode "<skill_dir>/scripts/create-regex-rule.js" \
--name "<RuleName>" --regex "<pattern>" --description "<desc>" \
--severity <1-5> --file-extensions ".cls,.trigger"code-analyzer.ymlsf code-analyzer rules --rule-selector regex:<RuleName>sf code-analyzer run --rule-selector regex:<RuleName> --target <violation-sample>sf code-analyzer run --rule-selector regex:<RuleName> --target <clean-sample>regex_ignoresamples/references/regex-rule-schema.mdnode "<skill_dir>/scripts/create-regex-rule.js" \
--name "<RuleName>" --regex "<pattern>" --description "<desc>" \
--severity <1-5> --file-extensions ".cls,.trigger"code-analyzer.ymlsf code-analyzer rules --rule-selector regex:<RuleName>sf code-analyzer run --rule-selector regex:<RuleName> --target <violation-sample>sf code-analyzer run --rule-selector regex:<RuleName> --target <clean-sample>regex_ignoresamples/for-eachforwhilesf code-analyzer ast-dump --file <sample.cls> --output-file <ast.xml>references/apex-ast-reference.mdreferences/xpath-patterns.md/Child//Descendantfor (x : [SELECT...])sf code-analyzer ast-dumpnode "<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>sf code-analyzer run --rule-selector pmd:<RuleName> --target <clean-sample.cls>samples/for-eachforwhilesf code-analyzer ast-dump --file <sample.cls> --output-file <ast.xml>references/apex-ast-reference.mdreferences/xpath-patterns.md/Child//Descendantfor (x : [SELECT...])sf code-analyzer ast-dumpnode "<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>sf code-analyzer run --rule-selector pmd:<RuleName> --target <clean-sample.cls>sf code-analyzer ast-dump --file <file>-meta.xml --language xml --output-file <ast.xml>"XmlEncoding is not a valid XML name"references/metadata-xml-rules.mdlocal-name()='ElementName'@Texttext()text()//*[@Text='ModifyAllData']../...//*[@Text='value']references/metadata-xml-rules.md.xml.permissionset-meta.xml.field-meta.xmlpath.extname().xml.xmlengines:
pmd:
file_extensions:
xml: [".xml"].permissionset-meta.xml/^[.][a-zA-Z0-9]+$/.xml.xmlnode "<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>.xmlsf code-analyzer run --rule-selector pmd:<RuleName> --target <clean-sample>.xml@Texttext()local-name().xmlsf code-analyzer ast-dump --file <file>-meta.xml --language xml --output-file <ast.xml>"XmlEncoding is not a valid XML name"references/metadata-xml-rules.mdlocal-name()='ElementName'@Texttext()text()//*[@Text='ModifyAllData']../...//*[@Text='value']references/metadata-xml-rules.md.xml.permissionset-meta.xml.field-meta.xmlpath.extname().xml.xmlengines:
pmd:
file_extensions:
xml: [".xml"].permissionset-meta.xml/^[.][a-zA-Z0-9]+$/.xml.xmlnode "<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>.xmlsf code-analyzer run --rule-selector pmd:<RuleName> --target <clean-sample>.xml@Texttext()local-name().xmlsf code-analyzer rules --rule-selector eslint@lwc/lwc/*no-restricted-globalsno-restricted-syntaxno-restricted-propertiesreferences/eslint-custom-plugins.mdreferences/eslint-rules-discovery.mdno-restricted-syntaxsf code-analyzer rules --rule-selector eslint@lwc/lwc/references/eslint-rules-discovery.mdno-restricted-globalsno-restricted-syntaxno-restricted-propertiessf code-analyzer rules --rule-selector eslint:<ruleName>no-restricted-globalsno-restricted-syntaxno-restricted-propertieseslint.config.jssf code-analyzer rulesnpm install --save-dev eslint-plugin-<name>eslint.config.js"error"engines.eslint.eslint_config_filecode-analyzer.ymlengines.eslint.eslint_config_filecode-analyzer.ymlsf code-analyzer rules --rule-selector eslint:<ruleName>eslint.config.jsmeta.docs.descriptionmeta.docs.urllwc/testSample/testSample.jssf code-analyzer run --rule-selector eslint:<ruleName> --target <test-sample>rm -rf <directory>rm <file>references/eslint-custom-plugins.mdsf code-analyzer rules --rule-selector eslint@lwc/lwc/*no-restricted-globalsno-restricted-syntaxno-restricted-propertiesreferences/eslint-custom-plugins.mdreferences/eslint-rules-discovery.mdno-restricted-syntaxsf code-analyzer rules --rule-selector eslint@lwc/lwc/references/eslint-rules-discovery.mdno-restricted-globalsno-restricted-syntaxno-restricted-propertiessf code-analyzer rules --rule-selector eslint:<ruleName>no-restricted-globalsno-restricted-syntaxno-restricted-propertieseslint.config.jssf code-analyzer rulesnpm install --save-dev eslint-plugin-<name>eslint.config.js"error"code-analyzer.ymlengines.eslint.eslint_config_filecode-analyzer.ymlengines.eslint.eslint_config_filesf code-analyzer rules --rule-selector eslint:<ruleName>eslint.config.jsmeta.docs.descriptionmeta.docs.urllwc/testSample/testSample.jssf code-analyzer run --rule-selector eslint:<ruleName> --target <test-sample>rm -rf <directory>references/eslint-custom-plugins.mdno-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.mdsf code-analyzer rules --rule-selector eslint | grep consoleno-consoleno-consoleno-setTimeoutno-restricted-globals@lwc/lwc/no-inner-html@lwc/lwc/no-inner-htmlimport.then().catch()references/eslint-rules-discovery.mdsf code-analyzer rules --rule-selector eslint | grep consoleno-consoleno-consoleno-setTimeoutno-restricted-globals@lwc/lwc/no-inner-html@lwc/lwc/no-inner-htmlimport.then().catch()references/eslint-rules-discovery.mdengines.pmd.custom_rulesetscode-analyzer.ymlreferences/advanced-pmd-patterns.mdcode-analyzer.ymlengines.pmd.custom_rulesetsreferences/advanced-pmd-patterns.mdRule 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)@Test = true()language="xml"规则计划:
1. RequireUserMode → PMD/XPath(需要通过AST排除测试类)
2. NoHardcodedIds → Regex(文本模式,无需结构上下文)
3. AuraEnabledCacheable → PMD/XPath(需要注解+DML结构检查)
4. CustomFieldDescription → PMD/XML(元数据管控)
5. NoSetTimeout → ESLint(JavaScript模式)@Test = true()language="xml"create-pmd-rule.jscreate-pmd-rule.jscode-analyzer.ymlengines.eslint.eslint_config_filecode-analyzer.ymlcode-analyzer.ymlengines.eslint.eslint_config_filecode-analyzer.yml| 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规则 | |
| 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. |
<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种循环类型: |
脚本运行后重写 | 脚本运行后切勿手动重写文件。仅添加顶层配置块(如 |
| 同时创建多个规则 — 一个失败破坏后续所有规则 | 一次创建一个规则,按顺序执行。完成每个规则的完整工作流程(创建→验证→测试)后再开始下一个。 |
<skill_dir>/references/troubleshooting.md| 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 |
| 需求 | 转交至 | 原因 |
|---|---|---|
| 创建规则后运行全面扫描 | | 扫描执行和结果展示 |
| 安装代码分析器 / 修复前置条件 | | 设置和故障排除 |
| 解释现有内置规则 | | 规则描述和文档查询 |
编辑 | | 配置管理 |
<skill_dir>scripts/./scripts/node "<skill_dir>/scripts/create-regex-rule.js" \
--name "RuleName" --regex "/pattern/flags" ...node scripts/create-regex-rule.js<skill_dir><skill_dir>scripts/./scripts/node "<skill_dir>/scripts/create-regex-rule.js" \
--name "RuleName" --regex "/pattern/flags" ...node scripts/create-regex-rule.js<skill_dir>| 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版本 |
| 元数据示例:流自动布局、流故障处理程序 |