Writing Custom Rules
Learn how to write custom lint rules using GritQL for project-specific validation.
Getting Started
Section titled “Getting Started”Prerequisites
Section titled “Prerequisites”- Understanding of FSH syntax
- Basic pattern matching concepts
- GritQL syntax basics (see GritQL Rules)
Create a directory for custom rules:
mkdir custom-rules
Configure FSH Lint to load custom rules:
{ "linter": { "ruleDirectories": ["./custom-rules"] }}
Rule Structure
Section titled “Rule Structure”A GritQL rule file (.grit
) contains:
- Metadata (language, description, severity)
- Pattern to match
- Conditions (optional)
- Message
- Fix (optional)
Example: Enforce Profile Naming
Section titled “Example: Enforce Profile Naming”Create custom-rules/profile-naming.grit
:
language fshdescription "Profiles must end with 'Profile'"severity error
pattern { Profile: $name}
where { !ends_with($name, "Profile")}
message "Profile name '${name}' should end with 'Profile'"
fix { Profile: `${name}Profile`}
Example: Require MS Flags
Section titled “Example: Require MS Flags”Create custom-rules/require-ms.grit
:
language fshdescription "Required fields must have MS flag"severity warning
pattern { Profile: $_ * $path 1..1 $flags}
where { !contains($flags, "MS")}
message "Add MS flag to required field: ${path}"
fix { * $path 1..1 MS}
Example: Enforce Descriptions
Section titled “Example: Enforce Descriptions”Create custom-rules/require-description.grit
:
language fshdescription "All profiles must have descriptions"severity warning
pattern { Profile: $name $...content}
where { !any_match($content, "Description:")}
message "Profile '${name}' is missing a description"
Testing Custom Rules
Section titled “Testing Custom Rules”Test your rules before deploying:
# Test on specific filesfsh-lint lint --rule custom/profile-naming test.fsh
# Run only custom rulesfsh-lint lint --only-custom **/*.fsh
Advanced Patterns
Section titled “Advanced Patterns”Complex Conditions
Section titled “Complex Conditions”pattern { Profile: $name * $path from $vs (required)}
where { ends_with($path, "code") and !is_uri($vs)}
message "Code bindings should use full URI: ${vs}"
Multiple Patterns
Section titled “Multiple Patterns”pattern { or { { ValueSet: $name } { CodeSystem: $name } }}
where { !contains($name, "VS") and !contains($name, "CS")}
Best Practices
Section titled “Best Practices”- Start Simple - Begin with basic patterns
- Test Thoroughly - Test on various FSH files
- Clear Messages - Help users understand violations
- Provide Fixes - Automate fixes when possible
- Document Rules - Explain the reasoning
- Performance - Avoid overly complex patterns
Organization-Wide Rules
Section titled “Organization-Wide Rules”Share rules across projects:
# Create shared rules repositorygit clone https://github.com/yourorg/fsh-lint-rules.git
# Reference in config{ "linter": { "ruleDirectories": [ "./fsh-lint-rules" ] }}
See Also
Section titled “See Also”- GritQL Documentation
- GritQL Rules
- Built-in Rules - Examples