@salesforce/afv-skills 1.28.0 → 1.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/dx-code-analyzer-configure/SKILL.md +31 -13
- package/skills/dx-code-analyzer-custom-rule-create/SKILL.md +484 -0
- package/skills/dx-code-analyzer-custom-rule-create/assets/pmd-ruleset-template.xml +31 -0
- package/skills/dx-code-analyzer-custom-rule-create/examples/metadata-xml-example-fields-api.md +87 -0
- package/skills/dx-code-analyzer-custom-rule-create/examples/metadata-xml-example-flows.md +105 -0
- package/skills/dx-code-analyzer-custom-rule-create/examples/metadata-xml-example-permissions.md +95 -0
- package/skills/dx-code-analyzer-custom-rule-create/examples/metadata-xml-examples.md +84 -0
- package/skills/dx-code-analyzer-custom-rule-create/examples/regex-examples.md +127 -0
- package/skills/dx-code-analyzer-custom-rule-create/examples/xpath-examples.md +227 -0
- package/skills/dx-code-analyzer-custom-rule-create/references/advanced-pmd-patterns.md +288 -0
- package/skills/dx-code-analyzer-custom-rule-create/references/apex-ast-reference.md +127 -0
- package/skills/dx-code-analyzer-custom-rule-create/references/eslint-custom-plugins.md +247 -0
- package/skills/dx-code-analyzer-custom-rule-create/references/eslint-rules-discovery.md +188 -0
- package/skills/dx-code-analyzer-custom-rule-create/references/eslint-tier2-configurable.md +114 -0
- package/skills/dx-code-analyzer-custom-rule-create/references/eslint-tier3-custom-plugins.md +113 -0
- package/skills/dx-code-analyzer-custom-rule-create/references/metadata-xml-rules.md +285 -0
- package/skills/dx-code-analyzer-custom-rule-create/references/regex-rule-schema.md +174 -0
- package/skills/dx-code-analyzer-custom-rule-create/references/troubleshooting.md +141 -0
- package/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns-governor-limits.md +83 -0
- package/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns-method-calls.md +108 -0
- package/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns-security.md +45 -0
- package/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns-structure.md +127 -0
- package/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns.md +131 -0
- package/skills/dx-code-analyzer-custom-rule-create/scripts/create-pmd-rule.js +209 -0
- package/skills/dx-code-analyzer-custom-rule-create/scripts/create-regex-rule.js +220 -0
- package/skills/dx-code-analyzer-run/SKILL.md +41 -8
- package/skills/mobile-platform-native-capabilities-integrate/SKILL.md +3 -3
- package/skills/platform-custom-field-generate/SKILL.md +86 -126
- package/skills/platform-custom-field-generate/references/advanced-picklists.md +590 -0
- package/skills/platform-value-set-generate/SKILL.md +305 -0
package/skills/dx-code-analyzer-custom-rule-create/examples/metadata-xml-example-fields-api.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Metadata XML Examples: Fields and API Version
|
|
2
|
+
|
|
3
|
+
[← Back to Metadata XML Examples Index](metadata-xml-examples.md)
|
|
4
|
+
|
|
5
|
+
## Example 2: Require Description on Custom Fields
|
|
6
|
+
|
|
7
|
+
**Problem:** Custom fields without descriptions make orgs hard to maintain.
|
|
8
|
+
|
|
9
|
+
**Target file:** `*.field-meta.xml`
|
|
10
|
+
|
|
11
|
+
**Sample violating metadata:**
|
|
12
|
+
```xml
|
|
13
|
+
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
14
|
+
<fullName>Revenue__c</fullName>
|
|
15
|
+
<label>Revenue</label>
|
|
16
|
+
<type>Currency</type>
|
|
17
|
+
<!-- No <description> element! -->
|
|
18
|
+
</CustomField>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**XPath (PMD 7):**
|
|
22
|
+
```xpath
|
|
23
|
+
//*[local-name()='CustomField'][not(*[local-name()='description']) or *[local-name()='description'][not(@Text)]]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**How it works:** Matches `CustomField` elements that either lack a `<description>` child entirely, or have one with no text content (`@Text` absent means empty).
|
|
27
|
+
|
|
28
|
+
**PMD ruleset:**
|
|
29
|
+
```xml
|
|
30
|
+
<rule name="FieldRequiresDescription"
|
|
31
|
+
language="xml"
|
|
32
|
+
message="Custom field must have a non-empty description"
|
|
33
|
+
class="net.sourceforge.pmd.lang.rule.xpath.XPathRule">
|
|
34
|
+
<description>Enforces that all custom fields have a description for documentation</description>
|
|
35
|
+
<priority>3</priority>
|
|
36
|
+
<properties>
|
|
37
|
+
<property name="xpath">
|
|
38
|
+
<value><![CDATA[
|
|
39
|
+
//*[local-name()='CustomField'][not(*[local-name()='description']) or *[local-name()='description'][not(@Text)]]
|
|
40
|
+
]]></value>
|
|
41
|
+
</property>
|
|
42
|
+
</properties>
|
|
43
|
+
</rule>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Example 3: Enforce Minimum API Version
|
|
49
|
+
|
|
50
|
+
**Problem:** Metadata using API versions older than 60.0 should be updated.
|
|
51
|
+
|
|
52
|
+
**Target file:** Any `*-meta.xml` with `<apiVersion>`
|
|
53
|
+
|
|
54
|
+
**Sample violating metadata:**
|
|
55
|
+
```xml
|
|
56
|
+
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
57
|
+
<apiVersion>52.0</apiVersion>
|
|
58
|
+
<status>Active</status>
|
|
59
|
+
</ApexClass>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**XPath (PMD 7):**
|
|
63
|
+
```xpath
|
|
64
|
+
//*[local-name()='apiVersion']/*[number(@Text) < 60]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**How it works:** Finds `<apiVersion>` elements, then navigates to their child text node with `/*`. The `@Text` attribute on the text node holds the value (e.g., "52.0"). `number(@Text)` converts it to a float, and flags if < 60.
|
|
68
|
+
|
|
69
|
+
⚠️ **Key insight:** `@Text` lives on CHILD text nodes, not on elements. You must use `/*` to reach the text node — putting `[@Text]` directly on the element (after `local-name()='apiVersion'`) returns 0 matches.
|
|
70
|
+
|
|
71
|
+
**PMD ruleset:**
|
|
72
|
+
```xml
|
|
73
|
+
<rule name="MinimumApiVersion"
|
|
74
|
+
language="xml"
|
|
75
|
+
message="API version must be 60.0 or higher — update this metadata"
|
|
76
|
+
class="net.sourceforge.pmd.lang.rule.xpath.XPathRule">
|
|
77
|
+
<description>Enforces minimum API version of 60.0 across all metadata</description>
|
|
78
|
+
<priority>3</priority>
|
|
79
|
+
<properties>
|
|
80
|
+
<property name="xpath">
|
|
81
|
+
<value><![CDATA[
|
|
82
|
+
//*[local-name()='apiVersion']/*[number(@Text) < 60]
|
|
83
|
+
]]></value>
|
|
84
|
+
</property>
|
|
85
|
+
</properties>
|
|
86
|
+
</rule>
|
|
87
|
+
```
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Metadata XML Examples: Flows
|
|
2
|
+
|
|
3
|
+
[← Back to Metadata XML Examples Index](metadata-xml-examples.md)
|
|
4
|
+
|
|
5
|
+
## Example 5: Require Flow Auto-Layout
|
|
6
|
+
|
|
7
|
+
**Problem:** Flows should use Auto-Layout canvas for consistency and maintainability.
|
|
8
|
+
|
|
9
|
+
**Target file:** `*.flow-meta.xml`
|
|
10
|
+
|
|
11
|
+
**Sample violating metadata:**
|
|
12
|
+
```xml
|
|
13
|
+
<Flow xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
14
|
+
<apiVersion>58.0</apiVersion>
|
|
15
|
+
<label>My Flow</label>
|
|
16
|
+
<processMetadataValues>
|
|
17
|
+
<name>CanvasMode</name>
|
|
18
|
+
<value><stringValue>FREE_FORM_CANVAS</stringValue></value>
|
|
19
|
+
</processMetadataValues>
|
|
20
|
+
</Flow>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**XPath (PMD 7 — flags FREE_FORM_CANVAS):**
|
|
24
|
+
```xpath
|
|
25
|
+
//*[@Text='FREE_FORM_CANVAS']/../..
|
|
26
|
+
[local-name()='value']
|
|
27
|
+
[ancestor::*[local-name()='processMetadataValues'][.//*[@Text='CanvasMode']]]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**How it works:** Finds text nodes with "FREE_FORM_CANVAS", navigates up to the `<value>` element, then confirms it's inside a `processMetadataValues` block that also contains "CanvasMode".
|
|
31
|
+
|
|
32
|
+
**PMD ruleset:**
|
|
33
|
+
```xml
|
|
34
|
+
<rule name="FlowMustUseAutoLayout"
|
|
35
|
+
language="xml"
|
|
36
|
+
message="Flows must use AUTO_LAYOUT_CANVAS mode"
|
|
37
|
+
class="net.sourceforge.pmd.lang.rule.xpath.XPathRule">
|
|
38
|
+
<description>Enforces auto-layout canvas mode on all flows for consistency</description>
|
|
39
|
+
<priority>3</priority>
|
|
40
|
+
<properties>
|
|
41
|
+
<property name="xpath">
|
|
42
|
+
<value><![CDATA[
|
|
43
|
+
//*[@Text='FREE_FORM_CANVAS']/../..
|
|
44
|
+
[local-name()='value']
|
|
45
|
+
[ancestor::*[local-name()='processMetadataValues'][.//*[@Text='CanvasMode']]]
|
|
46
|
+
]]></value>
|
|
47
|
+
</property>
|
|
48
|
+
</properties>
|
|
49
|
+
</rule>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Example 6: Flow Missing Fault Handler
|
|
55
|
+
|
|
56
|
+
**Problem:** Flow actions without fault connectors can fail silently.
|
|
57
|
+
|
|
58
|
+
**Target file:** `*.flow-meta.xml`
|
|
59
|
+
|
|
60
|
+
**Sample violating metadata:**
|
|
61
|
+
```xml
|
|
62
|
+
<Flow xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
63
|
+
<recordCreates>
|
|
64
|
+
<name>Create_Account</name>
|
|
65
|
+
<object>Account</object>
|
|
66
|
+
<connector>
|
|
67
|
+
<targetReference>Next_Step</targetReference>
|
|
68
|
+
</connector>
|
|
69
|
+
<!-- No <faultConnector> element! -->
|
|
70
|
+
</recordCreates>
|
|
71
|
+
</Flow>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**XPath:**
|
|
75
|
+
```xpath
|
|
76
|
+
//*[local-name()='Flow']/*[
|
|
77
|
+
local-name()='recordCreates' or local-name()='recordUpdates'
|
|
78
|
+
or local-name()='recordDeletes' or local-name()='recordLookups'
|
|
79
|
+
][
|
|
80
|
+
not(*[local-name()='faultConnector'])
|
|
81
|
+
]
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**PMD ruleset:**
|
|
85
|
+
```xml
|
|
86
|
+
<rule name="FlowActionRequiresFaultHandler"
|
|
87
|
+
language="xml"
|
|
88
|
+
message="Flow DML/query actions must have a fault connector for error handling"
|
|
89
|
+
class="net.sourceforge.pmd.lang.rule.xpath.XPathRule">
|
|
90
|
+
<description>Ensures all data operations in flows have fault paths</description>
|
|
91
|
+
<priority>2</priority>
|
|
92
|
+
<properties>
|
|
93
|
+
<property name="xpath">
|
|
94
|
+
<value><![CDATA[
|
|
95
|
+
//*[local-name()='Flow']/*[
|
|
96
|
+
local-name()='recordCreates' or local-name()='recordUpdates'
|
|
97
|
+
or local-name()='recordDeletes' or local-name()='recordLookups'
|
|
98
|
+
][
|
|
99
|
+
not(*[local-name()='faultConnector'])
|
|
100
|
+
]
|
|
101
|
+
]]></value>
|
|
102
|
+
</property>
|
|
103
|
+
</properties>
|
|
104
|
+
</rule>
|
|
105
|
+
```
|
package/skills/dx-code-analyzer-custom-rule-create/examples/metadata-xml-example-permissions.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Metadata XML Examples: Permissions
|
|
2
|
+
|
|
3
|
+
[← Back to Metadata XML Examples Index](metadata-xml-examples.md)
|
|
4
|
+
|
|
5
|
+
## Example 1: Flag ModifyAllData / ViewAllData Permissions
|
|
6
|
+
|
|
7
|
+
**Problem:** Permission sets granting ModifyAllData or ViewAllData are a security risk.
|
|
8
|
+
|
|
9
|
+
**Target file:** `*.permissionset-meta.xml`
|
|
10
|
+
|
|
11
|
+
**Sample violating metadata:**
|
|
12
|
+
```xml
|
|
13
|
+
<PermissionSet xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
14
|
+
<label>Power User</label>
|
|
15
|
+
<userPermissions>
|
|
16
|
+
<enabled>true</enabled>
|
|
17
|
+
<name>ModifyAllData</name>
|
|
18
|
+
</userPermissions>
|
|
19
|
+
</PermissionSet>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**XPath (PMD 7):**
|
|
23
|
+
```xpath
|
|
24
|
+
//*[@Text='ModifyAllData' or @Text='ViewAllData']/../..
|
|
25
|
+
[local-name()='userPermissions']
|
|
26
|
+
[.//*[@Text='true']]
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**How it works:**
|
|
30
|
+
1. `//*[@Text='ModifyAllData' or @Text='ViewAllData']` — find text node with dangerous permission name
|
|
31
|
+
2. `/../..` — navigate up: text node → `<name>` element → `<userPermissions>` parent
|
|
32
|
+
3. `[local-name()='userPermissions']` — confirm we're at the right element
|
|
33
|
+
4. `[.//*[@Text='true']]` — check that a descendant text node contains "true" (the `<enabled>` value)
|
|
34
|
+
|
|
35
|
+
**PMD ruleset:**
|
|
36
|
+
```xml
|
|
37
|
+
<rule name="NoDangerousPermissions"
|
|
38
|
+
language="xml"
|
|
39
|
+
message="Permission set grants ModifyAllData or ViewAllData — use specific object permissions instead"
|
|
40
|
+
class="net.sourceforge.pmd.lang.rule.xpath.XPathRule">
|
|
41
|
+
<description>Flags permission sets that grant ModifyAllData or ViewAllData</description>
|
|
42
|
+
<priority>1</priority>
|
|
43
|
+
<properties>
|
|
44
|
+
<property name="xpath">
|
|
45
|
+
<value><![CDATA[
|
|
46
|
+
//*[@Text='ModifyAllData' or @Text='ViewAllData']/../..
|
|
47
|
+
[local-name()='userPermissions']
|
|
48
|
+
[.//*[@Text='true']]
|
|
49
|
+
]]></value>
|
|
50
|
+
</property>
|
|
51
|
+
</properties>
|
|
52
|
+
</rule>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Example 4: No Field Permissions in Profiles
|
|
58
|
+
|
|
59
|
+
**Problem:** Field permissions should be managed via Permission Sets, not Profiles.
|
|
60
|
+
|
|
61
|
+
**Target file:** `*.profile-meta.xml`
|
|
62
|
+
|
|
63
|
+
**Sample violating metadata:**
|
|
64
|
+
```xml
|
|
65
|
+
<Profile xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
66
|
+
<fieldPermissions>
|
|
67
|
+
<editable>true</editable>
|
|
68
|
+
<field>Account.Revenue__c</field>
|
|
69
|
+
<readable>true</readable>
|
|
70
|
+
</fieldPermissions>
|
|
71
|
+
</Profile>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**XPath:**
|
|
75
|
+
```xpath
|
|
76
|
+
//*[local-name()='Profile']/*[local-name()='fieldPermissions']
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**PMD ruleset:**
|
|
80
|
+
```xml
|
|
81
|
+
<rule name="NoFieldPermissionsInProfile"
|
|
82
|
+
language="xml"
|
|
83
|
+
message="Field permissions should be in Permission Sets, not Profiles"
|
|
84
|
+
class="net.sourceforge.pmd.lang.rule.xpath.XPathRule">
|
|
85
|
+
<description>Profiles should not contain field-level security — use Permission Sets</description>
|
|
86
|
+
<priority>2</priority>
|
|
87
|
+
<properties>
|
|
88
|
+
<property name="xpath">
|
|
89
|
+
<value><![CDATA[
|
|
90
|
+
//*[local-name()='Profile']/*[local-name()='fieldPermissions']
|
|
91
|
+
]]></value>
|
|
92
|
+
</property>
|
|
93
|
+
</properties>
|
|
94
|
+
</rule>
|
|
95
|
+
```
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Metadata XML Rule Examples
|
|
2
|
+
|
|
3
|
+
Real-world custom PMD rules targeting Salesforce metadata XML files for org governance.
|
|
4
|
+
|
|
5
|
+
⚠️ **PMD 7 Note:** All examples use `@Text` for text content matching. The `text()` function does NOT work in PMD 7's XML language. See `references/metadata-xml-rules.md` for full details.
|
|
6
|
+
|
|
7
|
+
## Example Index
|
|
8
|
+
|
|
9
|
+
| # | Example | File |
|
|
10
|
+
|---|---------|------|
|
|
11
|
+
| 1 | Flag ModifyAllData / ViewAllData Permissions | [metadata-xml-example-permissions.md](metadata-xml-example-permissions.md) |
|
|
12
|
+
| 2 | Require Description on Custom Fields | [metadata-xml-example-fields-api.md](metadata-xml-example-fields-api.md) |
|
|
13
|
+
| 3 | Enforce Minimum API Version | [metadata-xml-example-fields-api.md](metadata-xml-example-fields-api.md) |
|
|
14
|
+
| 4 | No Field Permissions in Profiles | [metadata-xml-example-permissions.md](metadata-xml-example-permissions.md) |
|
|
15
|
+
| 5 | Require Flow Auto-Layout | [metadata-xml-example-flows.md](metadata-xml-example-flows.md) |
|
|
16
|
+
| 6 | Flow Missing Fault Handler | [metadata-xml-example-flows.md](metadata-xml-example-flows.md) |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## How to Create These
|
|
21
|
+
|
|
22
|
+
1. Run `sf code-analyzer ast-dump --file your-file.xml --language xml` to see the DOM structure. If ast-dump fails, read the raw XML file directly — the file content IS the AST.
|
|
23
|
+
2. Write XPath using `local-name()` for element matching and `@Text` for text content (NOT `text()`)
|
|
24
|
+
3. Navigate from text nodes to parent elements using `../..`
|
|
25
|
+
4. Scope to the correct metadata type by checking the root element or using `ancestor::`
|
|
26
|
+
5. Configure `file_extensions: { xml: [".xml"] }` in `code-analyzer.yml` (just `.xml` covers all compound metadata extensions)
|
|
27
|
+
6. Add the rule to a ruleset XML file with `language="xml"`
|
|
28
|
+
7. Reference the ruleset in `code-analyzer.yml` under `engines.pmd.custom_rulesets`
|
|
29
|
+
8. Validate: `sf code-analyzer rules --rule-selector pmd:RuleName`
|
|
30
|
+
9. Test positive + negative: run against both a violating and clean metadata file
|
|
31
|
+
|
|
32
|
+
## Complete Multi-Rule Ruleset Example
|
|
33
|
+
|
|
34
|
+
```xml
|
|
35
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
36
|
+
<ruleset name="MetadataGovernance"
|
|
37
|
+
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
|
38
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
39
|
+
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
|
|
40
|
+
|
|
41
|
+
<description>Org governance rules for Salesforce metadata</description>
|
|
42
|
+
|
|
43
|
+
<rule name="NoDangerousPermissions" language="xml"
|
|
44
|
+
message="Permission set grants ModifyAllData or ViewAllData"
|
|
45
|
+
class="net.sourceforge.pmd.lang.rule.xpath.XPathRule">
|
|
46
|
+
<priority>1</priority>
|
|
47
|
+
<properties>
|
|
48
|
+
<property name="xpath">
|
|
49
|
+
<value><![CDATA[
|
|
50
|
+
//*[@Text='ModifyAllData' or @Text='ViewAllData']/../..
|
|
51
|
+
[local-name()='userPermissions']
|
|
52
|
+
[.//*[@Text='true']]
|
|
53
|
+
]]></value>
|
|
54
|
+
</property>
|
|
55
|
+
</properties>
|
|
56
|
+
</rule>
|
|
57
|
+
|
|
58
|
+
<rule name="FieldRequiresDescription" language="xml"
|
|
59
|
+
message="Custom field must have a non-empty description"
|
|
60
|
+
class="net.sourceforge.pmd.lang.rule.xpath.XPathRule">
|
|
61
|
+
<priority>3</priority>
|
|
62
|
+
<properties>
|
|
63
|
+
<property name="xpath">
|
|
64
|
+
<value><![CDATA[
|
|
65
|
+
//*[local-name()='CustomField'][not(*[local-name()='description']) or *[local-name()='description'][not(@Text)]]
|
|
66
|
+
]]></value>
|
|
67
|
+
</property>
|
|
68
|
+
</properties>
|
|
69
|
+
</rule>
|
|
70
|
+
|
|
71
|
+
<rule name="MinimumApiVersion" language="xml"
|
|
72
|
+
message="API version must be 60.0 or higher"
|
|
73
|
+
class="net.sourceforge.pmd.lang.rule.xpath.XPathRule">
|
|
74
|
+
<priority>3</priority>
|
|
75
|
+
<properties>
|
|
76
|
+
<property name="xpath">
|
|
77
|
+
<value><![CDATA[
|
|
78
|
+
//*[local-name()='apiVersion']/*[number(@Text) < 60]
|
|
79
|
+
]]></value>
|
|
80
|
+
</property>
|
|
81
|
+
</properties>
|
|
82
|
+
</rule>
|
|
83
|
+
</ruleset>
|
|
84
|
+
```
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Regex Rule Examples
|
|
2
|
+
|
|
3
|
+
Real-world custom regex rules solving problems from the Code Analyzer community.
|
|
4
|
+
|
|
5
|
+
## Example 1: Ban Hardcoded Salesforce IDs
|
|
6
|
+
|
|
7
|
+
**Problem:** Developers hardcode record IDs that differ between orgs.
|
|
8
|
+
(GitHub issue #738 — community request for detecting bad patterns)
|
|
9
|
+
|
|
10
|
+
```yaml
|
|
11
|
+
engines:
|
|
12
|
+
regex:
|
|
13
|
+
custom_rules:
|
|
14
|
+
NoHardcodedSalesforceIds:
|
|
15
|
+
regex: "/['\"](?<target>0[a-zA-Z0-9]{14}(?:[a-zA-Z0-9]{3})?)['\"]/g"
|
|
16
|
+
description: "Detects hardcoded 15 or 18 character Salesforce record IDs"
|
|
17
|
+
violation_message: "Replace hardcoded ID with Custom Label, Custom Metadata, or Custom Setting"
|
|
18
|
+
severity: 2
|
|
19
|
+
tags: ["Custom", "Security"]
|
|
20
|
+
file_extensions: [".cls", ".trigger"]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Why this pattern:**
|
|
24
|
+
- Salesforce IDs are exactly **15 or 18 characters** (never 16 or 17)
|
|
25
|
+
- They always **start with `0`** (the key prefix)
|
|
26
|
+
- `0[a-zA-Z0-9]{14}` matches 15-char IDs (0 + 14 more)
|
|
27
|
+
- `(?:[a-zA-Z0-9]{3})?` optionally matches the 3-char case-safe suffix (making 18-char)
|
|
28
|
+
- `(?<target>...)` narrows the violation highlight to just the ID, not the surrounding quotes
|
|
29
|
+
- ⚠️ Do NOT use `{15,18}` — this also matches 16/17 char strings and false-positives on normal words like `'BusinessAccount'` or `'RecordTypeInfos'`
|
|
30
|
+
|
|
31
|
+
**Note on `regex_ignore`:** This field works **per-line**, not per-file. Adding `/@isTest/` only skips lines that literally contain `@isTest` — it does NOT exclude entire test classes. To exclude test files entirely, use `ignores.files` in `code-analyzer.yml` with a glob like `**/*Test.cls`.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Example 2: Flag TODO/FIXME Before Merge
|
|
36
|
+
|
|
37
|
+
**Problem:** Developers leave TODOs that never get resolved.
|
|
38
|
+
|
|
39
|
+
```yaml
|
|
40
|
+
engines:
|
|
41
|
+
regex:
|
|
42
|
+
custom_rules:
|
|
43
|
+
NoUnresolvedTodos:
|
|
44
|
+
regex: "/(?:TODO|FIXME|HACK|XXX)\\b/gi"
|
|
45
|
+
description: "Flags unresolved TODO/FIXME comments"
|
|
46
|
+
violation_message: "Resolve this TODO/FIXME before merging to main"
|
|
47
|
+
severity: 4
|
|
48
|
+
tags: ["Custom", "BestPractices"]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Example 3: Enforce WITH USER_MODE on SOQL
|
|
54
|
+
|
|
55
|
+
**Problem:** SOQL queries without FLS enforcement are a security risk.
|
|
56
|
+
|
|
57
|
+
```yaml
|
|
58
|
+
engines:
|
|
59
|
+
regex:
|
|
60
|
+
custom_rules:
|
|
61
|
+
RequireUserModeOnSoql:
|
|
62
|
+
regex: "/\\[\\s*SELECT(?![^\\]]*WITH\\s+(?:USER_MODE|SECURITY_ENFORCED))[^\\]]*\\]/gi"
|
|
63
|
+
description: "SOQL queries must use WITH USER_MODE or WITH SECURITY_ENFORCED"
|
|
64
|
+
violation_message: "Add WITH USER_MODE to this SOQL query for FLS enforcement"
|
|
65
|
+
severity: 2
|
|
66
|
+
tags: ["Custom", "Security"]
|
|
67
|
+
file_extensions: [".cls", ".trigger"]
|
|
68
|
+
regex_ignore: "/@isTest|@IsTest|@testSetup|@TestSetup/"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Example 4: Ban @SuppressWarnings and NOPMD
|
|
74
|
+
|
|
75
|
+
**Problem:** Teams want to prevent suppression of violations.
|
|
76
|
+
(GitHub issue #1972 — real user request)
|
|
77
|
+
|
|
78
|
+
```yaml
|
|
79
|
+
engines:
|
|
80
|
+
regex:
|
|
81
|
+
custom_rules:
|
|
82
|
+
ProhibitSuppressWarnings:
|
|
83
|
+
regex: "/@SuppressWarnings\\([^)]*\\)|\\/\\/\\s*NOPMD/gi"
|
|
84
|
+
description: "Prohibits suppression of code analysis warnings"
|
|
85
|
+
violation_message: "Fix the underlying issue instead of suppressing warnings"
|
|
86
|
+
severity: 2
|
|
87
|
+
tags: ["Custom", "BestPractices"]
|
|
88
|
+
file_extensions: [".cls", ".trigger"]
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Example 5: Detect Old API Versions in Metadata
|
|
94
|
+
|
|
95
|
+
**Problem:** Metadata files using API versions more than 2 years old.
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
engines:
|
|
99
|
+
regex:
|
|
100
|
+
custom_rules:
|
|
101
|
+
NoOldApiVersions:
|
|
102
|
+
regex: "/<apiVersion>(4[0-9]|5[0-5])\\.0<\\/apiVersion>/g"
|
|
103
|
+
description: "Detects metadata files using API version 55.0 or below"
|
|
104
|
+
violation_message: "Update API version to 60.0 or higher"
|
|
105
|
+
severity: 3
|
|
106
|
+
tags: ["Custom", "BestPractices"]
|
|
107
|
+
file_extensions: [".xml"]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Example 6: Enforce Test Class Naming Convention
|
|
113
|
+
|
|
114
|
+
**Problem:** Test classes should end with `_TEST` or `Test`.
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
117
|
+
engines:
|
|
118
|
+
regex:
|
|
119
|
+
custom_rules:
|
|
120
|
+
TestClassNaming:
|
|
121
|
+
regex: "/@(?:isTest|IsTest)(?:\\([^)]*\\))?\\s*(?:public|private)\\s+class\\s+(?!.*(?:_TEST|Test)\\b)\\w+/g"
|
|
122
|
+
description: "Test classes must end with _TEST or Test suffix"
|
|
123
|
+
violation_message: "Rename this test class to end with _TEST or Test (e.g., MyServiceTest)"
|
|
124
|
+
severity: 3
|
|
125
|
+
tags: ["Custom", "CodeStyle"]
|
|
126
|
+
file_extensions: [".cls"]
|
|
127
|
+
```
|