| name | rule-options |
| description | Add or modify rule options in SonarJS, including the fields array, SonarQube UI visibility, and Java check class configuration. Use when working on rule configurations. |
Architecture Overview
Rule options flow through two parallel paths:
SonarQube (HTTP/WebSocket):
SonarQube UI → Java Check Class → configurations() → analyzeProject() → ESLint Linter
External/gRPC:
External Client → gRPC → transformers.ts → parseParamValue() → ESLint Linter
SonarQube sends typed values; gRPC sends string key-value pairs that need type parsing.
Key Files per Rule
| File | Purpose |
|---|
rule.ts | ESLint rule implementation |
meta.ts | implementation, eslintId, schema, re-exports fields |
config.ts | fields array — source of truth for options |
generated-meta.ts | Auto-generated defaultOptions — do not edit |
The fields Array (config.ts)
The fields array defines options for SonarQube integration and default values.
import type { ESLintConfiguration } from '../helpers/configs.js';
export const fields = [
[
{
field: 'max',
displayName: 'maximumFunctionParameters',
description: 'Maximum authorized...',
default: 7,
},
{
field: 'ignoreIIFE',
default: false,
},
],
] as const satisfies ESLintConfiguration;
Field Properties
| Property | Required | Purpose |
|---|
field | Yes | ESLint/schema key name |
default | Yes | Default value; also determines type (number, string, boolean, array) |
description | For SQ visibility | Makes option visible in SonarQube UI |
displayName | No | SonarQube key if different from field |
items | For arrays | { type: 'string' } or { type: 'integer' } |
customDefault | No | Different default for SQ than ESLint |
fieldType | No | Override SQ field type (e.g., 'TEXT') |
Making Options Visible in SonarQube
A field appears in the SonarQube UI only if it has a description.
Fields without description are internal defaults invisible to users.
export const fields = [
[
{ field: 'ignore', default: [0, 1, -1, 24, 60] },
{ field: 'ignoreDefaultValues', default: true },
],
] as const satisfies ESLintConfiguration;
export const fields = [
[
{
field: 'passwordWords',
items: { type: 'string' },
description: 'Comma separated list of words identifying potential passwords.',
default: ['password', 'pwd', 'passwd', 'passphrase'],
},
],
] as const satisfies ESLintConfiguration;
Configuration Shapes
Object-style (most common)
export const fields = [
[
{ field: 'max', description: '...', default: 7 },
{ field: 'ignoreIIFE', description: '...', default: false },
],
] as const satisfies ESLintConfiguration;
Primitive (single value)
export const fields = [{ default: '^[a-z]+$' }] as const satisfies ESLintConfiguration;
Array options (comma-separated in SQ)
export const fields = [
[
{
field: 'passwordWords',
items: { type: 'string' },
description: 'Comma separated list...',
default: ['password', 'pwd'],
},
],
] as const satisfies ESLintConfiguration;
Type Parsing (gRPC)
String params from gRPC are parsed based on default type:
| Default Type | Input | Parsed |
|---|
number | "5" | 5 |
boolean | "true" | true |
string | "pattern" | "pattern" |
string[] | "a,b,c" | ["a","b","c"] |
number[] | "1,2,3" | [1,2,3] |
JSON Schema vs fields
| Aspect | JSON Schema (meta.ts) | fields (config.ts) |
|---|
| Purpose | ESLint validation | SQ UI + defaults + key mapping |
| Used by | ESLint at runtime | Java codegen, meta generation, linter |
| Required for | original rules with options | All rules with options |
For original rules, schema and fields must be kept in sync manually.
For decorated/external rules, schema is inherited from the external rule.
Adding Options to an Existing Rule
- Update
config.ts — add field to fields array
- Add
description if it should be visible in SonarQube
- Update
meta.ts schema (for original/decorated rules)
- Run
npm run generate-meta — updates generated-meta.ts with new defaultOptions
- Run
npm run generate-java-rule-classes — updates Java check classes
- Verify Java class has correct
configurations() method
Java Check Class (configurations())
@Override
public List<Object> configurations() {
return List.of(Map.of("max", maximum));
}
@RuleProperty(
key = "maximumFunctionParameters",
description = "Maximum authorized number of parameters",
defaultValue = "" + DEFAULT_MAX
)
private int maximum = DEFAULT_MAX;
Use MyRuleCheckTest.java to verify serialization:
assertThat(new MyRuleCheck().configurations()).containsExactly(Map.of("max", 7));
Key Mapping: SonarQube ↔ ESLint
When SQ and ESLint use different names:
{ field: 'max', displayName: 'maximumFunctionParameters', ... }
transformers.ts handles the SQ key → ESLint key mapping at runtime.