From 2873614e581e3d5adffde5b6e976024013f70dae Mon Sep 17 00:00:00 2001
From: David Schach <636977+dschach@users.noreply.github.com>
Date: Fri, 9 Oct 2026 19:06:18 +1100
Subject: [PATCH 1/3] chore(pmd): update PMD scanner with Code Analyzer and in
workflows
---
.eslintignore | 16 -
.github/workflows/ci.yml | 2 +-
.github/workflows/pmd.yml | 2 +-
.vscode/settings.json | 8 +-
README.md | 54 +-
code-analyzer.yml | 704 ++++++++++++++++++
.../main/default/classes/RecordTypes.cls | 21 +-
.../main/default/classes/RecordTypesTest.cls | 2 +-
package.json | 3 +-
...xPMDRules.xml => allApexPMDCategories.xml} | 18 +-
pmd/apexQuickStart.xml | 229 ------
pmd/apexStandardRules.xml | 388 ++++++++++
.../classes/UnpackagedRecordTypesTest.cls | 83 ++-
13 files changed, 1223 insertions(+), 307 deletions(-)
delete mode 100644 .eslintignore
create mode 100644 code-analyzer.yml
rename pmd/{allApexPMDRules.xml => allApexPMDCategories.xml} (56%)
delete mode 100644 pmd/apexQuickStart.xml
create mode 100644 pmd/apexStandardRules.xml
diff --git a/.eslintignore b/.eslintignore
deleted file mode 100644
index 5f7b681..0000000
--- a/.eslintignore
+++ /dev/null
@@ -1,16 +0,0 @@
-**/lwc/**/*.css
-**/lwc/**/*.html
-**/lwc/**/*.json
-**/lwc/**/*.svg
-**/lwc/**/*.xml
-**/aura/**/*.auradoc
-**/aura/**/*.cmp
-**/aura/**/*.css
-**/aura/**/*.design
-**/aura/**/*.evt
-**/aura/**/*.json
-**/aura/**/*.svg
-**/aura/**/*.tokens
-**/aura/**/*.xml
-**/aura/**/*.app
-.sfdx
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0f10ad8..f31e068 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -53,4 +53,4 @@ jobs:
~/pmd/bin/pmd --version
# Run PMD scan
- name: 'Run PMD scan'
- run: ~/pmd/bin/pmd check --dir force-app --rulesets pmd/apexQuickStart.xml --format text --no-cache --no-progress --minimum-priority "Medium High"
+ run: ~/pmd/bin/pmd check --dir force-app --rulesets pmd/apexStandardRules.xml --format text --no-cache --no-progress --minimum-priority "Medium High"
diff --git a/.github/workflows/pmd.yml b/.github/workflows/pmd.yml
index d222137..9e4faa6 100644
--- a/.github/workflows/pmd.yml
+++ b/.github/workflows/pmd.yml
@@ -25,7 +25,7 @@ jobs:
id: pmd
uses: pmd/pmd-github-action@v2
with:
- rulesets: 'pmd/apexQuickStart.xml'
+ rulesets: 'pmd/apexStandardRules.xml'
sourcePath: 'force-app'
analyzeModifiedFilesOnly: false
- name: Upload SARIF file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index a47a61d..0e5242f 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -2,7 +2,7 @@
"apexdox.docblock.alignItems": true,
"apexPMD.enableCache": true,
"apexPMD.rulesets": [
- "pmd/apexQuickStart.xml"
+ "pmd/apexStandardRules.xml"
],
"apexPMD.runOnFileChange": true,
"apexPMD.runOnFileOpen": true,
@@ -23,5 +23,9 @@
"**/node_modules": true
},
"visualforce.format.endWithNewline": true,
- "xml.preferences.showSchemaDocumentationType": "none"
+ "xml.preferences.showSchemaDocumentationType": "none",
+ "codeAnalyzer.ruleSelectors": "pmd:(Apex,all-apex)",
+ "codeAnalyzer.severity 1": "Error",
+ "codeAnalyzer.severity 2": "Error",
+ "codeAnalyzer.severity 5": "Info"
}
\ No newline at end of file
diff --git a/README.md b/README.md
index e2ee3b5..f305274 100644
--- a/README.md
+++ b/README.md
@@ -53,51 +53,55 @@ To set up a scratch org without creating a Record Type, run `bash scripts/orgini
## [Changelog](./CHANGELOG.md)
-- 2024-03
+- 2026-10
- - All methods are now case-insensitive
- - Dynamic describe methods remove need for global describe (faster code!)
- - Move Solution tests - does not increase coverage - to unpackaged test class
+ - Install Salesforce Code Analyzer and update PMD ruleset
-- 2024-02
+- 2024-03
- - Enhance SelectList methods
- - Update to API 60.0
- - Increase code coverage and test cases
+ - All methods are now case-insensitive
+ - Dynamic describe methods remove need for global describe (faster code!)
+ - Move Solution tests - does not increase coverage - to unpackaged test class
-- 2023-09
+- 2024-02
- - Overload getRecordTypeFromId so it doesn't require a SobjectType string
- - Release unlocked package
+ - Enhance SelectList methods
+ - Update to API 60.0
+ - Increase code coverage and test cases
-- 2023-08
+- 2023-09
- - Add methods to get default RecordTypeId, handling situation where no RT is on the Profile but at least one is avaialble via Permission Set.
- - Add test methods against Account and Solution objects, as we assume Solution has no defined record types. (Change for your org if you have them.)
- - Include table of all methods on documentation site
+ - Overload getRecordTypeFromId so it doesn't require a SobjectType string
+ - Release unlocked package
-- 2022-03
+- 2023-08
- - BREAKING CHANGE: Replaced "DeveloperName" with "DevName" in all method names. Update your code to refer to the new methods.
+ - Add methods to get default RecordTypeId, handling situation where no RT is on the Profile but at least one is avaialble via Permission Set.
+ - Add test methods against Account and Solution objects, as we assume Solution has no defined record types. (Change for your org if you have them.)
+ - Include table of all methods on documentation site
-- 2022-03
+- 2022-03
- - Add maps Id => Name and Id => DeveloperName for ease of use when wanting to refer to a record type by Id without including the object, since Id is globally unique
+ - BREAKING CHANGE: Replaced "DeveloperName" with "DevName" in all method names. Update your code to refer to the new methods.
-- 2022-01
- - Initial Release
+- 2022-03
+
+ - Add maps Id => Name and Id => DeveloperName for ease of use when wanting to refer to a record type by Id without including the object, since Id is globally unique
+
+- 2022-01
+ - Initial Release
## Code Header
Written by Evan Callahan, copyright © 2010 Groundwire
-- This program is released under the [GNU General Public License](./LICENSE). http://www.gnu.org/licenses/
-- This class is meant to allow for access to Record Type information from within other classes.
-- It is called statically, and therefore will supply the same information to all calls made from within one transaction, or set of trigger calls. This is beneficial because this info should be the same for all calls in a transaction, and by calling it statically we reduce the calls that are made, making the total transaction more efficient.
+- This program is released under the [GNU General Public License](./LICENSE). http://www.gnu.org/licenses/
+- This class is meant to allow for access to Record Type information from within other classes.
+- It is called statically, and therefore will supply the same information to all calls made from within one transaction, or set of trigger calls. This is beneficial because this info should be the same for all calls in a transaction, and by calling it statically we reduce the calls that are made, making the total transaction more efficient.
Updated by David Schach, copyright © X-Squared on Demand
-- Usage recommendation: Always use DeveloperName instead of Name, as this is more likely to be hard-coded in places, while the Name is actually a label and may change (especially due to user language).
+- Usage recommendation: Always use DeveloperName instead of Name, as this is more likely to be hard-coded in places, while the Name is actually a label and may change (especially due to user language).
# Library Methods
diff --git a/code-analyzer.yml b/code-analyzer.yml
new file mode 100644
index 0000000..844abe5
--- /dev/null
+++ b/code-analyzer.yml
@@ -0,0 +1,704 @@
+# ======================================================================
+# CODE ANALYZER CONFIGURATION
+# To learn more about this configuration, visit:
+# https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/config-custom.html
+# ======================================================================
+
+# The absolute folder path to which all other path values in this configuration may be relative to.
+# If unspecified, or if specified as null, then the value is automatically chosen to be the parent folder of your Code Analyzer
+# configuration file if it exists, or the current working directory otherwise.
+config_root: null # Last calculated by the config command as: "/Users/dschach/Documents/VSCode/record-types"
+
+# Folder where to store log files. May be an absolute path or a path relative to config_root.
+# If unspecified, or if specified as null, then the value is automatically chosen to be your machine's default temporary directory.
+log_folder: null # Last calculated by the config command as: "/var/folders/59/sdcp21jd4cj3q3_jjvfl7ydw0000gn/T"
+
+# Level at which to log messages to log files.
+# Possible values are:
+# 1 or 'Error' - Includes only error messages in the log.
+# 2 or 'Warn' - Includes warning and error messages in the log.
+# 3 or 'Info' - Includes informative, warning, and error messages in the log.
+# 4 or 'Debug' - Includes debug, informative, warning, and error messages in the log.
+# 5 or 'Fine' - Includes fine detail, debug, informative, warning, and error messages in the log.
+# If unspecified, or if specified as null, then the 'Debug' log level will be used.
+log_level: 4
+
+# Configuration for ignoring files during analysis.
+# files: An array of glob patterns specifying files to exclude from scanning.
+# ---- [Example usage]: ---------------------
+# ignores:
+# files:
+# - "**/node_modules/**"
+# - "**/*.test.js"
+# -------------------------------------------
+ignores:
+ files: []
+
+# Configuration for inline and bulk suppressions.
+# disable_suppressions: Boolean to disable processing of suppression markers.
+# {file_path}: Array of bulk suppression rules for specific files or folders.
+# ---- [Example usage]: ---------------------
+# suppressions:
+# disable_suppressions: false
+# "src/legacy.js":
+# - rule_selector: "eslint:no-console"
+# max_suppressed_violations: 5
+# -------------------------------------------
+suppressions:
+ disable_suppressions: false
+
+# Rule override settings of the format rules.{engine_name}.{rule_name}.{property_name} = {override_value} where:
+# {engine_name} is the name of the engine containing the rule that you want to override.
+# {rule_name} is the name of the rule that you want to override.
+# {property_name} can either be:
+# 'severity' - [Optional] The severity level value that you want to use to override the default severity level for the rule
+# Possible values: 1 or 'Critical', 2 or 'High', 3 or 'Moderate', 4 or 'Low', 5 or 'Info'
+# 'tags' - [Optional] The string array of tag values that you want to use to override the default tags for the rule
+# 'disabled' - [Optional] Boolean value to disable the rule for all files. When set to true, the rule will not run during analysis
+# ---- [Example usage]: ---------------------
+# rules:
+# eslint:
+# sort-vars:
+# severity: "Info"
+# tags: ["Recommended", "Suggestion"]
+# regex:
+# NoTrailingWhiteSpace:
+# disabled: true
+# -------------------------------------------
+rules:
+ # ======================================================================
+ # PMD ENGINE RULE OVERRIDES
+ # ======================================================================
+ pmd:
+ 'AnnotationsNamingConventions':
+ severity: 3 # Modified from: 4
+ tags: # Modified from: ["Recommended","CodeStyle","Apex"]
+ - Recommended
+ - CodeStyle
+ - Apex
+ - all-apex
+ 'ApexAssertionsShouldIncludeMessage':
+ severity: 3
+ tags: # Modified from: ["BestPractices","Apex"]
+ - BestPractices
+ - Apex
+ - all-apex
+ 'ApexBadCrypto':
+ severity: 3 # Modified from: 2
+ tags: # Modified from: ["Recommended","Security","Apex"]
+ - Recommended
+ - Security
+ - Apex
+ - all-apex
+ 'ApexCRUDViolation':
+ severity: 3 # Modified from: 2
+ tags: # Modified from: ["Recommended","Security","Apex"]
+ - Recommended
+ - Security
+ - Apex
+ - all-apex
+ 'ApexCSRF':
+ severity: 3 # Modified from: 1
+ tags: # Modified from: ["Recommended","Security","Apex"]
+ - Recommended
+ - Security
+ - Apex
+ - all-apex
+ 'ApexDangerousMethods':
+ severity: 3
+ tags: # Modified from: ["Recommended","Security","Apex"]
+ - Recommended
+ - Security
+ - Apex
+ - all-apex
+ 'ApexDoc':
+ severity: 3 # Modified from: 4
+ tags: # Modified from: ["Recommended","Documentation","Apex"]
+ - Recommended
+ - Documentation
+ - Apex
+ - all-apex
+ 'ApexInsecureEndpoint':
+ severity: 3 # Modified from: 2
+ tags: # Modified from: ["Recommended","Security","Apex"]
+ - Recommended
+ - Security
+ - Apex
+ - all-apex
+ 'ApexOpenRedirect':
+ severity: 3 # Modified from: 2
+ tags: # Modified from: ["Recommended","Security","Apex"]
+ - Recommended
+ - Security
+ - Apex
+ - all-apex
+ 'ApexSharingViolations':
+ severity: 3
+ tags: # Modified from: ["Recommended","Security","Apex"]
+ - Recommended
+ - Security
+ - Apex
+ - all-apex
+ 'ApexSOQLInjection':
+ severity: 3 # Modified from: 2
+ tags: # Modified from: ["Recommended","Security","Apex"]
+ - Recommended
+ - Security
+ - Apex
+ - all-apex
+ 'ApexSuggestUsingNamedCred':
+ severity: 3 # Modified from: 2
+ tags: # Modified from: ["Recommended","Security","Apex"]
+ - Recommended
+ - Security
+ - Apex
+ - all-apex
+ 'ApexUnitTestClassShouldHaveAsserts':
+ severity: 4 # Modified from: 3
+ tags: # Modified from: ["Recommended","BestPractices","Apex"]
+ - Recommended
+ - BestPractices
+ - Apex
+ - all-apex
+ 'ApexUnitTestClassShouldHaveRunAs':
+ disabled: true
+ severity: 3 # Modified from: 4
+ tags: # Modified from: ["Recommended","BestPractices","Apex"]
+ - Recommended
+ - BestPractices
+ - Apex
+ - all-apex
+ 'ApexUnitTestMethodShouldHaveIsTestAnnotation':
+ severity: 3 # Modified from: 2
+ tags: # Modified from: ["Recommended","BestPractices","Apex"]
+ - Recommended
+ - BestPractices
+ - Apex
+ - all-apex
+ 'ApexUnitTestShouldNotUseSeeAllDataTrue':
+ severity: 3 # Modified from: 2
+ tags: # Modified from: ["Recommended","BestPractices","Apex"]
+ - Recommended
+ - BestPractices
+ - Apex
+ - all-apex
+ 'ApexXSSFromEscapeFalse':
+ severity: 3 # Modified from: 2
+ tags: # Modified from: ["Recommended","Security","Apex"]
+ - Recommended
+ - Security
+ - Apex
+ - all-apex
+ 'ApexXSSFromURLParam':
+ severity: 3 # Modified from: 2
+ tags: # Modified from: ["Recommended","Security","Apex"]
+ - Recommended
+ - Security
+ - Apex
+ - all-apex
+ 'AvoidBooleanMethodParameters':
+ severity: 3
+ tags: # Modified from: ["Recommended","Design","Apex"]
+ - Recommended
+ - Design
+ - Apex
+ - all-apex
+ 'AvoidChangeProtectionUnprotected':
+ severity: 1
+ tags:
+ - AppExchange
+ - Security
+ - Apex
+ 'AvoidDebugStatements':
+ severity: 4
+ tags: # Modified from: ["Recommended","Performance","Apex"]
+ - Recommended
+ - Performance
+ - Apex
+ - all-apex
+ 'AvoidDeeplyNestedIfStmts':
+ severity: 3
+ tags: # Modified from: ["Recommended","Design","Apex"]
+ - Recommended
+ - Design
+ - Apex
+ - all-apex
+ 'AvoidDirectAccessTriggerMap':
+ severity: 3
+ tags: # Modified from: ["Recommended","ErrorProne","Apex"]
+ - Recommended
+ - ErrorProne
+ - Apex
+ - all-apex
+ 'AvoidFutureAnnotation':
+ severity: 4
+ tags: # Modified from: ["Recommended","BestPractices","Apex"]
+ - Recommended
+ - BestPractices
+ - Apex
+ - all-apex
+ 'AvoidGetInstanceWithTaint':
+ severity: 3
+ tags:
+ - AppExchange
+ - Security
+ - Apex
+ 'AvoidGlobalInstallUninstallHandlers':
+ severity: 1
+ tags:
+ - AppExchange
+ - Security
+ - Apex
+ 'AvoidGlobalModifier':
+ severity: 3
+ tags: # Modified from: ["Recommended","BestPractices","Apex"]
+ - Recommended
+ - BestPractices
+ - Apex
+ - all-apex
+ 'AvoidHardcodedCredentialsInFieldDecls':
+ severity: 3
+ tags:
+ - AppExchange
+ - Security
+ - Apex
+ 'AvoidHardcodedCredentialsInHttpHeader':
+ severity: 3
+ tags:
+ - AppExchange
+ - Security
+ - Apex
+ 'AvoidHardcodedCredentialsInSetPassword':
+ severity: 1
+ tags:
+ - AppExchange
+ - Security
+ - Apex
+ 'AvoidHardcodedCredentialsInVarAssign':
+ severity: 3
+ tags:
+ - AppExchange
+ - Security
+ - Apex
+ 'AvoidHardcodedCredentialsInVarDecls':
+ severity: 3
+ tags:
+ - AppExchange
+ - Security
+ - Apex
+ 'AvoidHardcodingId':
+ severity: 3
+ tags: # Modified from: ["Recommended","ErrorProne","Apex"]
+ - Recommended
+ - ErrorProne
+ - Apex
+ - all-apex
+ 'AvoidInterfaceAsMapKey':
+ severity: 3
+ tags: # Modified from: ["Recommended","ErrorProne","Apex"]
+ - Recommended
+ - ErrorProne
+ - Apex
+ - all-apex
+ 'AvoidInvalidCrudContentDistribution':
+ severity: 3
+ tags:
+ - AppExchange
+ - Security
+ - Apex
+ 'AvoidLogicInTrigger':
+ severity: 3
+ tags: # Modified from: ["Recommended","BestPractices","Apex"]
+ - Recommended
+ - BestPractices
+ - Apex
+ - all-apex
+ 'AvoidNonExistentAnnotations':
+ severity: 3 # Modified from: 4
+ tags: # Modified from: ["Recommended","ErrorProne","Apex"]
+ - Recommended
+ - ErrorProne
+ - Apex
+ - all-apex
+ 'AvoidNonRestrictiveQueries':
+ severity: 3 # Modified from: 4
+ tags: # Modified from: ["Recommended","Performance","Apex"]
+ - Recommended
+ - Performance
+ - Apex
+ - all-apex
+ 'AvoidSecurityEnforcedOldApiVersion':
+ severity: 3
+ tags:
+ - AppExchange
+ - Security
+ - Apex
+ 'AvoidStatefulDatabaseResult':
+ severity: 3
+ tags: # Modified from: ["Recommended","ErrorProne","Apex"]
+ - Recommended
+ - ErrorProne
+ - Apex
+ - all-apex
+ 'AvoidUnauthorizedApiSessionIdInApex':
+ severity: 3
+ tags:
+ - AppExchange
+ - Security
+ - Apex
+ 'AvoidUnauthorizedGetSessionIdInApex':
+ severity: 3
+ tags:
+ - AppExchange
+ - Security
+ - Apex
+ 'AvoidUnsafePasswordManagementUse':
+ severity: 1
+ tags:
+ - AppExchange
+ - Security
+ - Apex
+ 'ClassNamingConventions':
+ severity: 3
+ tags: # Modified from: ["Recommended","CodeStyle","Apex"]
+ - Recommended
+ - CodeStyle
+ - Apex
+ - all-apex
+ 'CognitiveComplexity':
+ disabled: true
+ severity: 3
+ tags:
+ - Recommended
+ - Design
+ - Apex
+ 'CyclomaticComplexity':
+ severity: 3
+ tags: # Modified from: ["Recommended","Design","Apex"]
+ - Recommended
+ - Design
+ - Apex
+ - all-apex
+ 'DebugsShouldUseLoggingLevel':
+ severity: 4
+ tags: # Modified from: ["Recommended","BestPractices","Apex"]
+ - Recommended
+ - BestPractices
+ - Apex
+ - all-apex
+ 'EagerlyLoadedDescribeSObjectResult':
+ severity: 3 # Modified from: 2
+ tags: # Modified from: ["Recommended","Performance","Apex"]
+ - Recommended
+ - Performance
+ - Apex
+ - all-apex
+ 'EmptyCatchBlock':
+ severity: 3 # Modified from: 2
+ tags: # Modified from: ["Recommended","ErrorProne","Apex"]
+ - Recommended
+ - ErrorProne
+ - Apex
+ - all-apex
+ 'EmptyIfStmt':
+ severity: 3
+ tags: # Modified from: ["Recommended","ErrorProne","Apex"]
+ - Recommended
+ - ErrorProne
+ - Apex
+ - all-apex
+ 'EmptyStatementBlock':
+ severity: 3
+ tags: # Modified from: ["Recommended","ErrorProne","Apex"]
+ - Recommended
+ - ErrorProne
+ - Apex
+ - all-apex
+ 'EmptyTryOrFinallyBlock':
+ severity: 3
+ tags: # Modified from: ["Recommended","ErrorProne","Apex"]
+ - Recommended
+ - ErrorProne
+ - Apex
+ - all-apex
+ 'EmptyWhileStmt':
+ severity: 3
+ tags: # Modified from: ["Recommended","ErrorProne","Apex"]
+ - Recommended
+ - ErrorProne
+ - Apex
+ - all-apex
+ 'ExcessiveClassLength':
+ disabled: true
+ severity: 3
+ tags:
+ - Design
+ - Apex
+ 'ExcessiveParameterList':
+ severity: 3
+ tags: # Modified from: ["Recommended","Design","Apex"]
+ - Recommended
+ - Design
+ - Apex
+ - all-apex
+ 'ExcessivePublicCount':
+ severity: 3
+ tags: # Modified from: ["Recommended","Design","Apex"]
+ - Recommended
+ - Design
+ - Apex
+ - all-apex
+ 'FieldDeclarationsShouldBeAtStart':
+ severity: 3
+ tags:
+ - Recommended
+ - CodeStyle
+ - Apex
+ 'FieldNamingConventions':
+ severity: 3
+ tags: # Modified from: ["Recommended","CodeStyle","Apex"]
+ - Recommended
+ - CodeStyle
+ - Apex
+ - all-apex
+ 'ForLoopsMustUseBraces':
+ severity: 2 # Modified from: 3
+ tags: # Modified from: ["Recommended","CodeStyle","Apex"]
+ - Recommended
+ - CodeStyle
+ - Apex
+ - all-apex
+ 'FormalParameterNamingConventions':
+ severity: 3
+ tags: # Modified from: ["Recommended","CodeStyle","Apex"]
+ - Recommended
+ - CodeStyle
+ - Apex
+ - all-apex
+ 'IfElseStmtsMustUseBraces':
+ severity: 2 # Modified from: 3
+ tags: # Modified from: ["Recommended","CodeStyle","Apex"]
+ - Recommended
+ - CodeStyle
+ - Apex
+ - all-apex
+ 'IfStmtsMustUseBraces':
+ severity: 2 # Modified from: 3
+ tags: # Modified from: ["Recommended","CodeStyle","Apex"]
+ - Recommended
+ - CodeStyle
+ - Apex
+ - all-apex
+ 'InaccessibleAuraEnabledGetter':
+ severity: 3
+ tags:
+ - Recommended
+ - ErrorProne
+ - Apex
+ 'InvocableClassNoArgConstructor':
+ severity: 3
+ tags: # Modified from: ["Recommended","ErrorProne","Apex"]
+ - Recommended
+ - ErrorProne
+ - Apex
+ - all-apex
+ 'LocalVariableNamingConventions':
+ severity: 3
+ tags: # Modified from: ["Recommended","CodeStyle","Apex"]
+ - Recommended
+ - CodeStyle
+ - Apex
+ - all-apex
+ 'MethodNamingConventions':
+ severity: 3
+ tags: # Modified from: ["Recommended","CodeStyle","Apex"]
+ - Recommended
+ - CodeStyle
+ - Apex
+ - all-apex
+ 'MethodWithSameNameAsEnclosingClass':
+ severity: 3
+ tags: # Modified from: ["Recommended","ErrorProne","Apex"]
+ - Recommended
+ - ErrorProne
+ - Apex
+ - all-apex
+ 'NcssConstructorCount':
+ disabled: true
+ severity: 4
+ tags:
+ - Design
+ - Apex
+ 'NcssCount':
+ severity: 3
+ tags: # Modified from: ["Recommended","Apex","Custom"]
+ - Recommended
+ - Apex
+ - Custom
+ - all-apex
+ 'NcssMethodCount':
+ disabled: true
+ severity: 4
+ tags:
+ - Design
+ - Apex
+ 'NcssTypeCount':
+ disabled: true
+ severity: 4
+ tags:
+ - Design
+ - Apex
+ 'OneDeclarationPerLine':
+ severity: 3
+ tags: # Modified from: ["Recommended","CodeStyle","Apex"]
+ - Recommended
+ - CodeStyle
+ - Apex
+ - all-apex
+ 'OperationWithHighCostInLoop':
+ severity: 3
+ tags: # Modified from: ["Recommended","Performance","Apex"]
+ - Recommended
+ - Performance
+ - Apex
+ - all-apex
+ 'OperationWithLimitsInLoop':
+ severity: 2 # Modified from: 3
+ tags: # Modified from: ["Recommended","Performance","Apex"]
+ - Recommended
+ - Performance
+ - Apex
+ - all-apex
+ 'OverrideBothEqualsAndHashcode':
+ severity: 2
+ tags:
+ - Recommended
+ - ErrorProne
+ - Apex
+ 'PropertyNamingConventions':
+ severity: 3
+ tags: # Modified from: ["Recommended","CodeStyle","Apex"]
+ - Recommended
+ - CodeStyle
+ - Apex
+ - all-apex
+ 'QueueableWithoutFinalizer':
+ severity: 4
+ tags: # Modified from: ["Recommended","BestPractices","Apex"]
+ - Recommended
+ - BestPractices
+ - Apex
+ - all-apex
+ 'StdCyclomaticComplexity':
+ severity: 3
+ tags: # Modified from: ["Design","Apex"]
+ - Design
+ - Apex
+ - all-apex
+ 'TestMethodsMustBeInTestClasses':
+ severity: 3
+ tags: # Modified from: ["Recommended","ErrorProne","Apex"]
+ - Recommended
+ - ErrorProne
+ - Apex
+ - all-apex
+ 'TooManyFields':
+ severity: 3
+ tags: # Modified from: ["Recommended","Design","Apex"]
+ - Recommended
+ - Design
+ - Apex
+ - all-apex
+ 'TypeShadowsBuiltInNamespace':
+ severity: 2
+ tags: # Modified from: ["Recommended","ErrorProne","Apex"]
+ - Recommended
+ - ErrorProne
+ - Apex
+ - all-apex
+ 'UnusedLocalVariable':
+ severity: 2 # Modified from: 3
+ tags: # Modified from: ["Recommended","BestPractices","Apex"]
+ - Recommended
+ - BestPractices
+ - Apex
+ - all-apex
+ 'UnusedMethod':
+ severity: 3
+ tags: # Modified from: ["Recommended","Design","Apex"]
+ - Recommended
+ - Design
+ - Apex
+ - all-apex
+ 'WhileLoopsMustUseBraces':
+ severity: 2 # Modified from: 3
+ tags: # Modified from: ["Recommended","CodeStyle","Apex"]
+ - Recommended
+ - CodeStyle
+ - Apex
+ - all-apex
+
+# Engine specific custom configuration settings of the format engines.{engine_name}.{property_name} = {value} where:
+# {engine_name} is the name of the engine containing the setting that you want to override.
+# {property_name} is the name of a property that you would like to override.
+# Each engine may have its own set of properties available to help customize that particular engine's behavior.
+engines:
+ # ======================================================================
+ # PMD ENGINE CONFIGURATION
+ # To learn more about this configuration, visit:
+ # https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/engine-pmd.html#pmd-configuration-reference
+ # ======================================================================
+ pmd:
+ # Whether to turn off the 'pmd' engine so that it is not included when running Code Analyzer commands.
+ disable_engine: false
+
+ # Indicates the specific 'java' command associated with the JRE or JDK to use for the 'pmd' engine.
+ # May be provided as the name of a command that exists on the path, or an absolute file path location.
+ # If unspecified, or specified as null, then an attempt will be made to automatically discover a 'java' command from your environment.
+ java_command: null # Last calculated by the config command as: "java"
+
+ # Specifies the list of file extensions to associate to each rule language.
+ # The rule(s) associated with a given language will run against all the files in your workspace containing one of
+ # the specified file extensions. Each file extension can only be associated to one language. If a specific language
+ # is not specified, then a set of default file extensions for that language will be used.
+ file_extensions:
+ apex:
+ - .cls
+ - .trigger
+ html:
+ - .html
+ - .htm
+ - .xhtml
+ - .xht
+ - .shtml
+ - .cmp
+ javascript:
+ - .js
+ - .cjs
+ - .mjs
+ typescript:
+ - .ts
+ visualforce:
+ - .page
+ - .component
+ xml:
+ - .xml
+
+ # List of jar files and/or folders to add the Java classpath when running PMD.
+ # Each entry may be given as an absolute path or a relative path to 'config_root'.
+ # This field is primarily used to supply custom Java based rule definitions to PMD.
+ # See https://pmd.github.io/pmd/pmd_userdocs_extending_writing_java_rules.html
+ java_classpath_entries: []
+
+ # List of xml ruleset files containing custom PMD rules to be made available for rule selection.
+ # Each ruleset must be an xml file that is either:
+ # - on disk (provided as an absolute path or a relative path to 'config_root')
+ # - or a relative resource found on the Java classpath.
+ # Not all custom rules can be fully defined within an xml ruleset file. For example, Java based rules may be defined in jar files.
+ # In these cases, you will need to also add your additional files to the Java classpath using the 'java_classpath_entries' field.
+ # See https://pmd.github.io/pmd/pmd_userdocs_making_rulesets.html to learn more about PMD rulesets.
+ custom_rulesets: # Modified from: []
+ - pmd/apexStandardRules.xml
+# ======================================================================
+# END OF CODE ANALYZER CONFIGURATION
+# ======================================================================
diff --git a/force-app/main/default/classes/RecordTypes.cls b/force-app/main/default/classes/RecordTypes.cls
index 8498a31..467de7f 100644
--- a/force-app/main/default/classes/RecordTypes.cls
+++ b/force-app/main/default/classes/RecordTypes.cls
@@ -1,4 +1,3 @@
-@SuppressWarnings('PMD.AvoidGlobalModifier, PMD.CyclomaticComplexity')
/**
* @description This class is allows for easy, readable access to Record Type information from other classes.
*
@@ -39,6 +38,7 @@
* @group RecordTypes
* @see RecordTypesTest
*/
+@SuppressWarnings('PMD.NcssMethodCount, PMD.AvoidGlobalModifier, PMD.CyclomaticComplexity, PMD.CognitiveComplexity')
global inherited sharing class RecordTypes {
/**
* @description Hold Sobject describe results as we need them
@@ -87,7 +87,9 @@ global inherited sharing class RecordTypes {
private static Map recordTypesIdMap {
get {
if (recordTypesIdMap == null) {
- recordTypesIdMap = new Map([SELECT Id, DeveloperName, Name, SobjectType FROM RecordType]);
+ recordTypesIdMap = new Map(
+ [SELECT Id, DeveloperName, Name, SobjectType FROM RecordType LIMIT 2000]
+ );
}
return recordTypesIdMap;
}
@@ -109,7 +111,7 @@ global inherited sharing class RecordTypes {
SObjectDescribeOptions.DEFERRED
);
sObjectDescribes.put(sObjectName, describes[0]);
- } catch (InvalidParameterValueException e) {
+ } catch (RecordTypeLibraryException e) {
return;
}
}
@@ -648,6 +650,7 @@ global inherited sharing class RecordTypes {
* @param disableUnavailable Should we disable unavailable RTs in the SelectList?
* @return `List` Visualforce SelectOption list
*/
+ @SuppressWarnings('PMD.AvoidBooleanMethodParameters')
global static List getAllRecordTypesForSelectList(String objectName, Boolean disableUnavailable) {
String sObjectName = objectName.toLowerCase();
List recordTypesOptions = new List();
@@ -731,6 +734,12 @@ global inherited sharing class RecordTypes {
return isDefaultMapping ?? false;
}
+ /**
+ * @description Exception thrown by the Record Types library
+ */
+ public class RecordTypeLibraryException extends Exception {
+ }
+
/* private class RTInfoWrapper {
private String developerName;
private String name;
@@ -752,10 +761,10 @@ global inherited sharing class RecordTypes {
} */
/**
- * @description If we are running a test, clear sObject maps. We do this to avoid using @testVisible on the maps themselves
- *
This is private and testvisible so it cannot be called in production code context
+ * @description If we are running a test, clear sObject maps. We do this to avoid using @TestVisible on the maps themselves
+ *
This is private and TestVisible so it cannot be called in production code context
*/
- @testVisible
+ @TestVisible
private static void clearMapsInTest() {
if (Test.isRunningTest()) {
RecordTypes.recordTypesById.clear();
diff --git a/force-app/main/default/classes/RecordTypesTest.cls b/force-app/main/default/classes/RecordTypesTest.cls
index a5cb4b5..f69a03e 100644
--- a/force-app/main/default/classes/RecordTypesTest.cls
+++ b/force-app/main/default/classes/RecordTypesTest.cls
@@ -10,7 +10,7 @@
* @group RecordTypes
* @see RecordTypes
*/
-@SuppressWarnings('PMD.ApexUnitTestClassShouldHaveRunAs')
+@SuppressWarnings('PMD.ApexUnitTestClassShouldHaveRunAs,PMD.NcssCount')
@IsTest
private class RecordTypesTest {
/**
diff --git a/package.json b/package.json
index ea3ba6e..9e5ccac 100644
--- a/package.json
+++ b/package.json
@@ -13,15 +13,14 @@
"apex:local:start": "node node_modules/prettier-plugin-apex/dist/bin/start-apex-server.js",
"apex:local:stop": "node node_modules/prettier-plugin-apex/dist/bin/stop-apex-server.js",
"build": ". scripts/packagedev/build.sh",
+ "codeanalyzer:config": "echo 'y' | sf code-analyzer config --include-unmodified-rules --rule-selector all --config-file code-analyzer.yml --output-file code-analyzer.yml",
"devhub-x2od": "sf config set target-dev-hub=x2od",
"docs:setup": ". doc-assets/setupApexDox.sh",
"orginit": ". scripts/orginit.sh",
"prepare": "husky",
"precommit": "lint-staged",
- "prettier:apex:local": "prettier --apex-standalone-parser built-in --write \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"",
"prettier:apex:verify": "prettier --list-different \"force-app/**/*.{cls,trigger}\"",
"prettier:docs": "prettier --write \"doc*/*.{html,css}\"",
- "prettier:verify:apex:local": "prettier --apex-standalone-parser built-in --check \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"",
"prettier:verify": "prettier --list-different \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"",
"prettier": "prettier --write \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"",
"prune": "git branch | grep -v \"main\" | xargs git branch -D",
diff --git a/pmd/allApexPMDRules.xml b/pmd/allApexPMDCategories.xml
similarity index 56%
rename from pmd/allApexPMDRules.xml
rename to pmd/allApexPMDCategories.xml
index 35e27cc..9bbf703 100644
--- a/pmd/allApexPMDRules.xml
+++ b/pmd/allApexPMDCategories.xml
@@ -1,19 +1,23 @@
-
+
-
+ xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
This ruleset was created from Apex category
+ .*/.sfdx/.*
+ .*/.sf/.*
-
+
+
+
+
+
+
-
diff --git a/pmd/apexQuickStart.xml b/pmd/apexQuickStart.xml
deleted file mode 100644
index 916cb1f..0000000
--- a/pmd/apexQuickStart.xml
+++ /dev/null
@@ -1,229 +0,0 @@
-
-
- Quickstart configuration of PMD for Salesforce Apex. Adapted for David Schach frameworks.
-
-
-
- 3
-
-
-
-
-
- 3
-
-
-
-
-
- 3
-
-
-
-
-
- 3
-
-
-
-
-
- 3
-
-
-
-
-
- 3
-
-
-
-
-
- 3
-
-
-
-
-
- 3
-
-
-
-
-
- 3
-
-
- 3
-
-
-
-
-
- 1
-
-
- 3
-
-
- 3
-
-
- 3
-
-
- 2
-
-
-
- 3
-
-
- 5
-
-
-
-
-
- 3
-
-
- 3
-
-
- 2
-
-
-
-
- 3
-
-
- 3
-
-
- 3
-
-
- 3
-
-
-
-
- 4
-
-
- 3
-
-
-
-
-
-
-
- 3
-
-
- 3
-
-
- 3
-
-
- 3
-
-
- 3
-
-
- 3
-
-
- 3
-
-
- 3
-
-
- 3
-
-
- 3
-
-
- 3
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 3
-
-
- 2
-
-
- 2
-
-
- 3
-
-
- 3
-
-
-
-
- 3
-
-
-
-
-
- 3
-
-
-
-
-
-
-
-
-
- 4
-
-
- 1
-
-
-
-
-
diff --git a/pmd/apexStandardRules.xml b/pmd/apexStandardRules.xml
new file mode 100644
index 0000000..f8eeedd
--- /dev/null
+++ b/pmd/apexStandardRules.xml
@@ -0,0 +1,388 @@
+
+
+ All standard rules for Salesforce Apex. Adapted for David Schach.
+
+
+
+ 3
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+
+
+
+ 5
+
+
+
+ 4
+
+
+
+ 5
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+ 3
+
+
+
+ 2
+
+
+
+
+ 4
+
+
+
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+
+ 1
+
+
+
+ 1
+
+
+
+ 1
+
+
+
+ 1
+
+
+
+
+ 3
+
+
+
+
+
+
+
+ 2
+
+
+
+ 2
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+ 3
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+ 3
+
+
+
+ 2
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+ 2
+
+
+
+ 3
+
+
+
+ 1
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+
+ 3
+
+
+
+ 3
+
+
+
+ 4
+
+
+
+
+
+
+ 1
+
+
+
+ 3
+
+
+
+ 2
+
+
diff --git a/unpackaged/main/default/classes/UnpackagedRecordTypesTest.cls b/unpackaged/main/default/classes/UnpackagedRecordTypesTest.cls
index fe384ca..61046a8 100644
--- a/unpackaged/main/default/classes/UnpackagedRecordTypesTest.cls
+++ b/unpackaged/main/default/classes/UnpackagedRecordTypesTest.cls
@@ -7,7 +7,7 @@
* @since 2024
*/
@IsTest
-private class UnpackagedRecordTypesTest {
+private without sharing class UnpackagedRecordTypesTest {
/**
* @description Test against Account, an object with record types in package testing, but with lowercase RT name
*
Assumes we have a record type called `Default` and tests `Default`
@@ -18,11 +18,20 @@ private class UnpackagedRecordTypesTest {
private static void testAccountRecTypes() {
//Test with Account
- Assert.isNotNull(RecordTypes.getRecordTypesForObject('Account'), 'A real sobject should have at least Master record type');
+ Assert.isNotNull(
+ RecordTypes.getRecordTypesForObject('Account'),
+ 'A real sobject should have at least Master record type'
+ );
Assert.isNotNull(RecordTypes.getRecordTypeIdFromName('Account', 'Default'), 'Default record type should exist');
- Assert.isNotNull(RecordTypes.getRecordTypeDevNameFromName('Account', 'Default'), 'Default record type should exist');
+ Assert.isNotNull(
+ RecordTypes.getRecordTypeDevNameFromName('Account', 'Default'),
+ 'Default record type should exist'
+ );
- Assert.isNotNull(RecordTypes.getRecordTypeNameFromDevName('Account', 'Default'), 'Default record type should exist');
+ Assert.isNotNull(
+ RecordTypes.getRecordTypeNameFromDevName('Account', 'Default'),
+ 'Default record type should exist'
+ );
Assert.isNotNull(RecordTypes.getRecordTypeIdFromDevName('Account', 'Default'), 'Default record type should exist');
Assert.isNull(RecordTypes.getRecordTypeNameFromId('Account', null), 'Null record type should not exist');
@@ -45,7 +54,10 @@ private class UnpackagedRecordTypesTest {
'Our default Account RT should be "Master" because we assigned via permission set'
);
- Assert.isNotNull(RecordTypes.getRecordTypeDevNameIdMap('Account'), 'A real sobject should return at least an empty map');
+ Assert.isNotNull(
+ RecordTypes.getRecordTypeDevNameIdMap('Account'),
+ 'A real sobject should return at least an empty map'
+ );
Assert.isNotNull(
RecordTypes.getAvailableRecordTypeDevNameIdMap('Account'),
@@ -72,11 +84,20 @@ private class UnpackagedRecordTypesTest {
private static void testAccountRecTypesLowercaseRT() {
//Test with Account
- Assert.isNotNull(RecordTypes.getRecordTypesForObject('Account'), 'A real sobject should have at least Master record type');
+ Assert.isNotNull(
+ RecordTypes.getRecordTypesForObject('Account'),
+ 'A real sobject should have at least Master record type'
+ );
Assert.isNotNull(RecordTypes.getRecordTypeIdFromName('Account', 'default'), 'default record type should exist');
- Assert.isNotNull(RecordTypes.getRecordTypeDevNameFromName('Account', 'default'), 'default record type should exist');
+ Assert.isNotNull(
+ RecordTypes.getRecordTypeDevNameFromName('Account', 'default'),
+ 'default record type should exist'
+ );
- Assert.isNotNull(RecordTypes.getRecordTypeNameFromDevName('Account', 'default'), 'default record type should exist');
+ Assert.isNotNull(
+ RecordTypes.getRecordTypeNameFromDevName('Account', 'default'),
+ 'default record type should exist'
+ );
Assert.isNotNull(RecordTypes.getRecordTypeIdFromDevName('Account', 'default'), 'default record type should exist');
Assert.isNotNull(RecordTypes.getRecordTypeIdFromDevName('Account', 'default'), 'default record type should exist');
@@ -93,23 +114,44 @@ private class UnpackagedRecordTypesTest {
//Test with Solution
Assert.isNull(RecordTypes.getRecordTypeIdFromName('Solution', 'BogusRT'), 'BogusRT record type should not exist');
- Assert.isNull(RecordTypes.getRecordTypeDevNameFromName('Solution', 'BogusRT'), 'BogusRT record type should not exist');
+ Assert.isNull(
+ RecordTypes.getRecordTypeDevNameFromName('Solution', 'BogusRT'),
+ 'BogusRT record type should not exist'
+ );
- Assert.isNull(RecordTypes.getRecordTypeNameFromDevName('Solution', 'BogusRT'), 'BogusRT record type should not exist');
- Assert.isNull(RecordTypes.getRecordTypeIdFromDevName('Solution', 'BogusRT'), 'BogusRT record type should not exist');
+ Assert.isNull(
+ RecordTypes.getRecordTypeNameFromDevName('Solution', 'BogusRT'),
+ 'BogusRT record type should not exist'
+ );
+ Assert.isNull(
+ RecordTypes.getRecordTypeIdFromDevName('Solution', 'BogusRT'),
+ 'BogusRT record type should not exist'
+ );
Assert.isNull(RecordTypes.getRecordTypeNameFromId('Solution', null), 'Null record type should not exist');
Assert.isNull(RecordTypes.getRecordTypeDevNameFromId('Solution', null), 'Null record type should not exist');
- Assert.isNull(RecordTypes.getRecordTypeIdFromDevName('Solution', 'BogusRT'), 'BogusRT record type should not exist');
+ Assert.isNull(
+ RecordTypes.getRecordTypeIdFromDevName('Solution', 'BogusRT'),
+ 'BogusRT record type should not exist'
+ );
Assert.isNull(RecordTypes.getRecordTypeIdFromName('Solution', 'BogusRT'), 'BogusRT record type should not exist');
- Assert.isNotNull(RecordTypes.getDefaultRecordTypeName('Solution'), 'A real sobject should have at least Master record type');
- Assert.isNotNull(RecordTypes.getDefaultRecordTypeDevName('Solution'), 'A real sobject should have at least Master record type');
+ Assert.isNotNull(
+ RecordTypes.getDefaultRecordTypeName('Solution'),
+ 'A real sobject should have at least Master record type'
+ );
+ Assert.isNotNull(
+ RecordTypes.getDefaultRecordTypeDevName('Solution'),
+ 'A real sobject should have at least Master record type'
+ );
// For coverage, we are assuming that Solution has no record types
RecordTypes.getDefaultRecordTypeId('Solution');
- Assert.isNotNull(RecordTypes.getRecordTypeDevNameIdMap('Solution'), 'a real sobject should return at least an empty map');
+ Assert.isNotNull(
+ RecordTypes.getRecordTypeDevNameIdMap('Solution'),
+ 'a real sobject should return at least an empty map'
+ );
Assert.isNotNull(
RecordTypes.getAvailableRecordTypeDevNameIdMap('Solution'),
@@ -121,7 +163,10 @@ private class UnpackagedRecordTypesTest {
);
resetTest();
- Assert.isFalse(RecordTypes.getAllRecordTypesForSelectList('Solution').isEmpty(), 'Should return at least a single item select list');
+ Assert.isFalse(
+ RecordTypes.getAllRecordTypesForSelectList('Solution').isEmpty(),
+ 'Should return at least a single item select list'
+ );
}
/**
@@ -130,7 +175,11 @@ private class UnpackagedRecordTypesTest {
@IsTest
static void testMethodsAfterReset() {
resetTest();
- List queriedRecordTypes = [SELECT Id, Name, DeveloperName FROM RecordType WHERE SObjectType = 'Account'];
+ List queriedRecordTypes = [
+ SELECT Id, Name, DeveloperName
+ FROM RecordType
+ WHERE SObjectType = 'Account'
+ ];
Assert.isNotNull(RecordTypes.getRecordTypeNameFromId(queriedRecordTypes[0].Id), 'Error');
}
From a4ad61e7629dfe8ccea3f4248e3e85267835b608 Mon Sep 17 00:00:00 2001
From: David Schach <636977+dschach@users.noreply.github.com>
Date: Fri, 9 Oct 2026 19:11:53 +1100
Subject: [PATCH 2/3] fix(RecordTypes): rethrow RecordTypeLibraryException in
fillMapsForObject
Co-Authored-By: Claude Sonnet 5.5
---
force-app/main/default/classes/RecordTypes.cls | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/force-app/main/default/classes/RecordTypes.cls b/force-app/main/default/classes/RecordTypes.cls
index 467de7f..e34d278 100644
--- a/force-app/main/default/classes/RecordTypes.cls
+++ b/force-app/main/default/classes/RecordTypes.cls
@@ -112,7 +112,8 @@ global inherited sharing class RecordTypes {
);
sObjectDescribes.put(sObjectName, describes[0]);
} catch (RecordTypeLibraryException e) {
- return;
+ throw e;
+ //return;
}
}
// get the sObject description
From dc4798d200005d7d22643034ab38edafc7f8e1f1 Mon Sep 17 00:00:00 2001
From: David Schach <636977+dschach@users.noreply.github.com>
Date: Fri, 9 Oct 2026 19:14:34 +1100
Subject: [PATCH 3/3] fix(RecordTypes): restore InvalidParameterValueException
handling
Co-Authored-By: Claude Sonnet 5.5
---
force-app/main/default/classes/RecordTypes.cls | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/force-app/main/default/classes/RecordTypes.cls b/force-app/main/default/classes/RecordTypes.cls
index e34d278..1af1c39 100644
--- a/force-app/main/default/classes/RecordTypes.cls
+++ b/force-app/main/default/classes/RecordTypes.cls
@@ -111,9 +111,8 @@ global inherited sharing class RecordTypes {
SObjectDescribeOptions.DEFERRED
);
sObjectDescribes.put(sObjectName, describes[0]);
- } catch (RecordTypeLibraryException e) {
- throw e;
- //return;
+ } catch (InvalidParameterValueException e) {
+ return;
}
}
// get the sObject description
@@ -735,12 +734,6 @@ global inherited sharing class RecordTypes {
return isDefaultMapping ?? false;
}
- /**
- * @description Exception thrown by the Record Types library
- */
- public class RecordTypeLibraryException extends Exception {
- }
-
/* private class RTInfoWrapper {
private String developerName;
private String name;