eslint-plugin-code-style 1.7.4 → 1.7.6
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/CHANGELOG.md +23 -0
- package/README.md +15 -10
- package/index.js +108 -153
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [1.7.6] - 2026-02-02
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **`ternary-condition-multiline`** - Now depends only on operand count, not line length:
|
|
15
|
+
- ≤maxOperands (default: 3): Always collapse to single line regardless of line length
|
|
16
|
+
- \>maxOperands: Format multiline with each operand on its own line
|
|
17
|
+
- Removed `maxLineLength` option (no longer used)
|
|
18
|
+
- This aligns behavior with `multiline-if-conditions` rule
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## [1.7.5] - 2026-02-02
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **`ternary-condition-multiline`** - For ≤3 operands, always collapse to single line when `?` is on different line than condition end (enforces `condition ? value : value` format for simple ternaries)
|
|
27
|
+
- **`no-empty-lines-in-function-params`** - Add detection for empty lines in TSTypeLiteral (type annotation objects like `{ prop: Type }` in intersection types)
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
10
31
|
## [1.7.4] - 2026-02-02
|
|
11
32
|
|
|
12
33
|
### Fixed
|
|
@@ -1117,6 +1138,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
1117
1138
|
|
|
1118
1139
|
---
|
|
1119
1140
|
|
|
1141
|
+
[1.7.6]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.7.5...v1.7.6
|
|
1142
|
+
[1.7.5]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.7.4...v1.7.5
|
|
1120
1143
|
[1.7.4]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.7.3...v1.7.4
|
|
1121
1144
|
[1.7.3]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.7.2...v1.7.3
|
|
1122
1145
|
[1.7.2]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.7.1...v1.7.2
|
package/README.md
CHANGED
|
@@ -295,7 +295,7 @@ rules: {
|
|
|
295
295
|
| `if-statement-format` | `{` on same line as `if`/`else if`, `else` on same line as `}`, proper spacing 🔧 |
|
|
296
296
|
| `multiline-if-conditions` | Conditions exceeding threshold get one operand per line with proper indentation (default: >3) 🔧 ⚙️ |
|
|
297
297
|
| `no-empty-lines-in-switch-cases` | No empty line after `case X:` before code, no empty lines between cases 🔧 |
|
|
298
|
-
| `ternary-condition-multiline` |
|
|
298
|
+
| `ternary-condition-multiline` | ≤maxOperands always single line; >maxOperands multiline (based on operand count, not line length) 🔧 ⚙️ |
|
|
299
299
|
| **Function Rules** | |
|
|
300
300
|
| `function-call-spacing` | No space between function name and `(`: `fn()` not `fn ()` 🔧 |
|
|
301
301
|
| `function-declaration-style` | Auto-fix for `func-style`: converts function declarations to arrow expressions 🔧 |
|
|
@@ -1211,24 +1211,24 @@ switch (status) {
|
|
|
1211
1211
|
|
|
1212
1212
|
### `ternary-condition-multiline`
|
|
1213
1213
|
|
|
1214
|
-
**What it does:**
|
|
1215
|
-
-
|
|
1216
|
-
-
|
|
1214
|
+
**What it does:** Formats ternary expressions based on condition operand count:
|
|
1215
|
+
- ≤maxOperands (default: 3): Always collapse to single line regardless of line length
|
|
1216
|
+
- \>maxOperands: Expand to multiline with each operand on its own line
|
|
1217
1217
|
|
|
1218
|
-
**Why use it:**
|
|
1218
|
+
**Why use it:** Consistent formatting based on complexity, not line length. Simple conditions stay readable on one line; complex conditions get proper multiline formatting.
|
|
1219
1219
|
|
|
1220
1220
|
**Options:**
|
|
1221
1221
|
|
|
1222
1222
|
| Option | Type | Default | Description |
|
|
1223
1223
|
|--------|------|---------|-------------|
|
|
1224
|
-
| `maxOperands` | `integer` | `3` | Maximum operands to keep on single line |
|
|
1225
|
-
| `maxLineLength` | `integer` | `120` | Maximum line length for single-line ternaries |
|
|
1224
|
+
| `maxOperands` | `integer` | `3` | Maximum condition operands to keep ternary on single line |
|
|
1226
1225
|
|
|
1227
1226
|
```javascript
|
|
1228
|
-
// ✅ Good —
|
|
1227
|
+
// ✅ Good — ≤3 operands always on single line
|
|
1229
1228
|
const x = a && b && c ? "yes" : "no";
|
|
1229
|
+
const url = lang === "ar" ? `${apiEndpoints.exam.status}/${jobId}?lang=ar` : `${apiEndpoints.exam.status}/${jobId}`;
|
|
1230
1230
|
|
|
1231
|
-
// ✅ Good —
|
|
1231
|
+
// ✅ Good — >3 operands formatted multiline
|
|
1232
1232
|
const style = variant === "ghost"
|
|
1233
1233
|
|| variant === "ghost-danger"
|
|
1234
1234
|
|| variant === "muted"
|
|
@@ -1236,7 +1236,12 @@ const style = variant === "ghost"
|
|
|
1236
1236
|
? "transparent"
|
|
1237
1237
|
: "solid";
|
|
1238
1238
|
|
|
1239
|
-
// ❌ Bad —
|
|
1239
|
+
// ❌ Bad — ≤3 operands split across lines
|
|
1240
|
+
const x = a && b && c
|
|
1241
|
+
? "yes"
|
|
1242
|
+
: "no";
|
|
1243
|
+
|
|
1244
|
+
// ❌ Bad — >3 operands crammed on one line
|
|
1240
1245
|
const style = variant === "ghost" || variant === "ghost-danger" || variant === "muted" || variant === "primary" ? "transparent" : "solid";
|
|
1241
1246
|
```
|
|
1242
1247
|
|
package/index.js
CHANGED
|
@@ -3868,21 +3868,31 @@ const multilineIfConditions = {
|
|
|
3868
3868
|
* ───────────────────────────────────────────────────────────────
|
|
3869
3869
|
*
|
|
3870
3870
|
* Description:
|
|
3871
|
-
*
|
|
3872
|
-
*
|
|
3871
|
+
* Formats ternary expressions based on condition operand count:
|
|
3872
|
+
* - ≤maxOperands (default: 3): Always collapse to single line
|
|
3873
|
+
* - >maxOperands: Format multiline with each operand on its own line
|
|
3873
3874
|
*
|
|
3874
|
-
*
|
|
3875
|
+
* Options:
|
|
3876
|
+
* { maxOperands: 3 } - Maximum operands to keep on single line (default: 3)
|
|
3877
|
+
*
|
|
3878
|
+
* ✓ Good (≤3 operands - single line):
|
|
3875
3879
|
* const x = a && b && c ? "yes" : "no";
|
|
3880
|
+
* const url = lang === "ar" ? "/ar/path" : "/en/path";
|
|
3876
3881
|
*
|
|
3877
|
-
*
|
|
3878
|
-
*
|
|
3882
|
+
* ✓ Good (>3 operands - multiline):
|
|
3883
|
+
* const x = variant === "ghost"
|
|
3879
3884
|
* || variant === "ghost-danger"
|
|
3880
3885
|
* || variant === "muted"
|
|
3881
3886
|
* || variant === "primary"
|
|
3882
|
-
*
|
|
3883
|
-
*
|
|
3887
|
+
* ? "value1"
|
|
3888
|
+
* : "value2";
|
|
3884
3889
|
*
|
|
3885
|
-
* ✗ Bad:
|
|
3890
|
+
* ✗ Bad (≤3 operands split across lines):
|
|
3891
|
+
* const x = a && b && c
|
|
3892
|
+
* ? "yes"
|
|
3893
|
+
* : "no";
|
|
3894
|
+
*
|
|
3895
|
+
* ✗ Bad (>3 operands on single line):
|
|
3886
3896
|
* const x = variant === "ghost" || variant === "ghost-danger" || variant === "muted" || variant === "primary" ? "value1" : "value2";
|
|
3887
3897
|
*/
|
|
3888
3898
|
const ternaryConditionMultiline = {
|
|
@@ -3890,7 +3900,6 @@ const ternaryConditionMultiline = {
|
|
|
3890
3900
|
const sourceCode = context.sourceCode || context.getSourceCode();
|
|
3891
3901
|
const options = context.options[0] || {};
|
|
3892
3902
|
const maxOperands = options.maxOperands ?? 3;
|
|
3893
|
-
const maxLineLength = options.maxLineLength ?? 120;
|
|
3894
3903
|
|
|
3895
3904
|
// Check if node is wrapped in parentheses
|
|
3896
3905
|
const isParenthesizedHandler = (node) => {
|
|
@@ -4048,7 +4057,7 @@ const ternaryConditionMultiline = {
|
|
|
4048
4057
|
return false;
|
|
4049
4058
|
};
|
|
4050
4059
|
|
|
4051
|
-
// Handle simple ternaries - collapse to single line
|
|
4060
|
+
// Handle simple ternaries (≤maxOperands) - always collapse to single line
|
|
4052
4061
|
const handleSimpleTernaryHandler = (node) => {
|
|
4053
4062
|
const isOnSingleLine = node.loc.start.line === node.loc.end.line;
|
|
4054
4063
|
const hasOperatorOnOwnLine = isOperatorOnOwnLineHandler(node);
|
|
@@ -4068,46 +4077,15 @@ const ternaryConditionMultiline = {
|
|
|
4068
4077
|
|
|
4069
4078
|
// Calculate what the single line would look like
|
|
4070
4079
|
const singleLineText = getTernarySingleLineHandler(node);
|
|
4071
|
-
const indent = getLineIndentHandler(node);
|
|
4072
|
-
|
|
4073
|
-
// Check if the parent needs prefix text (like "const x = " or "key: ")
|
|
4074
|
-
let prefixLength = 0;
|
|
4075
|
-
const parent = node.parent;
|
|
4076
|
-
|
|
4077
|
-
if (parent && parent.type === "VariableDeclarator" && parent.init === node) {
|
|
4078
|
-
// Calculate prefix based on parent's start line (where "const x = " is)
|
|
4079
|
-
const varDecl = parent.parent;
|
|
4080
|
-
const declKeyword = varDecl ? sourceCode.getFirstToken(varDecl).value : "const";
|
|
4081
|
-
const varName = parent.id.name || sourceCode.getText(parent.id);
|
|
4082
|
-
|
|
4083
|
-
// Prefix is "const varName = " or similar
|
|
4084
|
-
prefixLength = declKeyword.length + 1 + varName.length + 3; // keyword + space + name + " = "
|
|
4085
|
-
} else if (parent && parent.type === "AssignmentExpression" && parent.right === node) {
|
|
4086
|
-
// Calculate prefix based on left side of assignment
|
|
4087
|
-
const leftText = sourceCode.getText(parent.left);
|
|
4088
|
-
|
|
4089
|
-
prefixLength = leftText.length + 3; // left + " = "
|
|
4090
|
-
} else if (parent && parent.type === "Property" && parent.value === node) {
|
|
4091
|
-
// Object property: key: ternary
|
|
4092
|
-
const keyText = sourceCode.getText(parent.key);
|
|
4093
|
-
|
|
4094
|
-
prefixLength = keyText.length + 2; // key + ": "
|
|
4095
|
-
}
|
|
4096
|
-
|
|
4097
|
-
// Check if single line would fit
|
|
4098
|
-
const totalLength = indent + prefixLength + singleLineText.length + 1;
|
|
4099
|
-
|
|
4100
|
-
if (totalLength <= maxLineLength) {
|
|
4101
|
-
context.report({
|
|
4102
|
-
fix: (fixer) => fixer.replaceText(node, singleLineText),
|
|
4103
|
-
message: "Simple ternary should be on a single line",
|
|
4104
|
-
node,
|
|
4105
|
-
});
|
|
4106
4080
|
|
|
4107
|
-
|
|
4108
|
-
|
|
4081
|
+
// For ≤maxOperands conditions, always collapse to single line regardless of length
|
|
4082
|
+
context.report({
|
|
4083
|
+
fix: (fixer) => fixer.replaceText(node, singleLineText),
|
|
4084
|
+
message: `Ternary with ≤${maxOperands} operands should be on a single line`,
|
|
4085
|
+
node,
|
|
4086
|
+
});
|
|
4109
4087
|
|
|
4110
|
-
return
|
|
4088
|
+
return true;
|
|
4111
4089
|
};
|
|
4112
4090
|
|
|
4113
4091
|
// Handle complex logical expressions - format multiline
|
|
@@ -4118,112 +4096,35 @@ const ternaryConditionMultiline = {
|
|
|
4118
4096
|
const testEndLine = test.loc.end.line;
|
|
4119
4097
|
const isMultiLine = testStartLine !== testEndLine;
|
|
4120
4098
|
|
|
4121
|
-
// ≤maxOperands operands:
|
|
4099
|
+
// ≤maxOperands operands: always collapse to single line (regardless of line length)
|
|
4122
4100
|
if (operands.length <= maxOperands) {
|
|
4123
|
-
const firstOperandStartLine = operands[0].loc.start.line;
|
|
4124
|
-
const allOperandsStartOnSameLine = operands.every(
|
|
4125
|
-
(op) => op.loc.start.line === firstOperandStartLine,
|
|
4126
|
-
);
|
|
4127
|
-
|
|
4128
|
-
const hasSplitBinaryExpression = operands.some(
|
|
4129
|
-
(op) => isBinaryExpressionSplitHandler(op),
|
|
4130
|
-
);
|
|
4131
|
-
|
|
4132
|
-
// Check if ? or : is on its own line without its value
|
|
4133
|
-
const hasOperatorOnOwnLine = isOperatorOnOwnLineHandler(node);
|
|
4134
|
-
|
|
4135
|
-
// Check if ternary is multiline (could be collapsed)
|
|
4136
|
-
const isTernaryMultiline = node.loc.start.line !== node.loc.end.line;
|
|
4137
|
-
|
|
4138
|
-
// Helper to build single line condition
|
|
4139
|
-
const buildSameLineHandler = (n) => {
|
|
4140
|
-
if (n.type === "LogicalExpression" && !isParenthesizedHandler(n)) {
|
|
4141
|
-
const leftText = buildSameLineHandler(n.left);
|
|
4142
|
-
const rightText = buildSameLineHandler(n.right);
|
|
4143
|
-
|
|
4144
|
-
return `${leftText} ${n.operator} ${rightText}`;
|
|
4145
|
-
}
|
|
4146
|
-
|
|
4147
|
-
if (n.type === "BinaryExpression" && isBinaryExpressionSplitHandler(n)) {
|
|
4148
|
-
return buildBinaryExpressionSingleLineHandler(n);
|
|
4149
|
-
}
|
|
4150
|
-
|
|
4151
|
-
return getSourceTextWithGroupsHandler(n);
|
|
4152
|
-
};
|
|
4153
|
-
|
|
4154
|
-
// Check if whole ternary can fit on one line
|
|
4155
|
-
const singleLineText = getTernarySingleLineHandler(node);
|
|
4156
|
-
const indent = getLineIndentHandler(node);
|
|
4157
|
-
|
|
4158
|
-
// Calculate prefix length for context
|
|
4159
|
-
let prefixLength = 0;
|
|
4160
|
-
const parent = node.parent;
|
|
4161
|
-
|
|
4162
|
-
if (parent && parent.type === "VariableDeclarator" && parent.init === node) {
|
|
4163
|
-
const varDecl = parent.parent;
|
|
4164
|
-
const declKeyword = varDecl ? sourceCode.getFirstToken(varDecl).value : "const";
|
|
4165
|
-
const varName = parent.id.name || sourceCode.getText(parent.id);
|
|
4166
|
-
|
|
4167
|
-
prefixLength = declKeyword.length + 1 + varName.length + 3;
|
|
4168
|
-
} else if (parent && parent.type === "AssignmentExpression" && parent.right === node) {
|
|
4169
|
-
const leftText = sourceCode.getText(parent.left);
|
|
4170
|
-
|
|
4171
|
-
prefixLength = leftText.length + 3;
|
|
4172
|
-
} else if (parent && parent.type === "Property" && parent.value === node) {
|
|
4173
|
-
const keyText = sourceCode.getText(parent.key);
|
|
4174
|
-
|
|
4175
|
-
prefixLength = keyText.length + 2;
|
|
4176
|
-
}
|
|
4177
|
-
|
|
4178
|
-
const totalLength = indent + prefixLength + singleLineText.length + 1;
|
|
4179
|
-
const canFitOnOneLine = totalLength <= maxLineLength;
|
|
4180
|
-
|
|
4181
4101
|
// Skip if branches have complex objects
|
|
4182
4102
|
const hasComplexBranches = hasComplexObjectHandler(node.consequent) || hasComplexObjectHandler(node.alternate);
|
|
4183
4103
|
|
|
4184
4104
|
// Skip nested ternaries
|
|
4185
4105
|
const hasNestedTernary = node.consequent.type === "ConditionalExpression" || node.alternate.type === "ConditionalExpression";
|
|
4186
4106
|
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
const needsOperatorFix = hasOperatorOnOwnLine;
|
|
4107
|
+
if (hasComplexBranches || hasNestedTernary) {
|
|
4108
|
+
return;
|
|
4109
|
+
}
|
|
4191
4110
|
|
|
4192
|
-
if
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
node,
|
|
4199
|
-
});
|
|
4200
|
-
} else if (needsOperatorFix) {
|
|
4201
|
-
// Format as proper multiline with ? and : on their own lines with values
|
|
4202
|
-
context.report({
|
|
4203
|
-
fix: (fixer) => {
|
|
4204
|
-
const lineText = sourceCode.lines[node.loc.start.line - 1];
|
|
4205
|
-
const baseIndent = lineText.match(/^\s*/)[0];
|
|
4206
|
-
const conditionIndent = baseIndent + " ";
|
|
4207
|
-
const conditionText = buildSameLineHandler(test);
|
|
4208
|
-
const consequentText = sourceCode.getText(node.consequent);
|
|
4209
|
-
const alternateText = sourceCode.getText(node.alternate);
|
|
4210
|
-
const newText = `${conditionText}\n${conditionIndent}? ${consequentText}\n${conditionIndent}: ${alternateText}`;
|
|
4211
|
-
|
|
4212
|
-
return fixer.replaceText(node, newText);
|
|
4213
|
-
},
|
|
4214
|
-
message: `Ternary with ≤${maxOperands} operands should have ? and : with their values on the same line`,
|
|
4215
|
-
node,
|
|
4216
|
-
});
|
|
4217
|
-
} else if (needsConditionFix) {
|
|
4218
|
-
// Otherwise just fix the condition to be on single line
|
|
4219
|
-
context.report({
|
|
4220
|
-
fix: (fixer) => fixer.replaceText(test, buildSameLineHandler(test)),
|
|
4221
|
-
message: `Ternary conditions with ≤${maxOperands} operands should be single line`,
|
|
4222
|
-
node: test,
|
|
4223
|
-
});
|
|
4224
|
-
}
|
|
4111
|
+
// Check if already properly formatted (single line)
|
|
4112
|
+
const isOnSingleLine = node.loc.start.line === node.loc.end.line;
|
|
4113
|
+
const hasOperatorOnOwnLine = isOperatorOnOwnLineHandler(node);
|
|
4114
|
+
|
|
4115
|
+
if (isOnSingleLine && !hasOperatorOnOwnLine) {
|
|
4116
|
+
return;
|
|
4225
4117
|
}
|
|
4226
4118
|
|
|
4119
|
+
// Collapse to single line
|
|
4120
|
+
const singleLineText = getTernarySingleLineHandler(node);
|
|
4121
|
+
|
|
4122
|
+
context.report({
|
|
4123
|
+
fix: (fixer) => fixer.replaceText(node, singleLineText),
|
|
4124
|
+
message: `Ternary with ≤${maxOperands} operands should be on a single line`,
|
|
4125
|
+
node,
|
|
4126
|
+
});
|
|
4127
|
+
|
|
4227
4128
|
return;
|
|
4228
4129
|
}
|
|
4229
4130
|
|
|
@@ -4379,21 +4280,15 @@ const ternaryConditionMultiline = {
|
|
|
4379
4280
|
};
|
|
4380
4281
|
},
|
|
4381
4282
|
meta: {
|
|
4382
|
-
docs: { description: "Enforce consistent ternary formatting:
|
|
4283
|
+
docs: { description: "Enforce consistent ternary formatting based on condition operand count: ≤maxOperands collapses to single line, >maxOperands expands to multiline" },
|
|
4383
4284
|
fixable: "code",
|
|
4384
4285
|
schema: [
|
|
4385
4286
|
{
|
|
4386
4287
|
additionalProperties: false,
|
|
4387
4288
|
properties: {
|
|
4388
|
-
maxLineLength: {
|
|
4389
|
-
default: 120,
|
|
4390
|
-
description: "Maximum line length for single-line ternaries (default: 120)",
|
|
4391
|
-
minimum: 80,
|
|
4392
|
-
type: "integer",
|
|
4393
|
-
},
|
|
4394
4289
|
maxOperands: {
|
|
4395
4290
|
default: 3,
|
|
4396
|
-
description: "Maximum operands to keep on single line (default: 3)",
|
|
4291
|
+
description: "Maximum condition operands to keep ternary on single line (default: 3). Ternaries with more operands are formatted multiline.",
|
|
4397
4292
|
minimum: 1,
|
|
4398
4293
|
type: "integer",
|
|
4399
4294
|
},
|
|
@@ -9857,14 +9752,74 @@ const noEmptyLinesInFunctionParams = {
|
|
|
9857
9752
|
});
|
|
9858
9753
|
};
|
|
9859
9754
|
|
|
9755
|
+
// Check TSTypeLiteral for empty lines (type annotation objects like { prop: Type })
|
|
9756
|
+
const checkTypeLiteralHandler = (node) => {
|
|
9757
|
+
if (!node.members || node.members.length === 0) return;
|
|
9758
|
+
|
|
9759
|
+
const firstMember = node.members[0];
|
|
9760
|
+
const lastMember = node.members[node.members.length - 1];
|
|
9761
|
+
|
|
9762
|
+
// Find opening brace
|
|
9763
|
+
const openBrace = sourceCode.getFirstToken(node);
|
|
9764
|
+
|
|
9765
|
+
if (openBrace && openBrace.value === "{") {
|
|
9766
|
+
// Check for empty line after opening brace
|
|
9767
|
+
if (firstMember.loc.start.line - openBrace.loc.end.line > 1) {
|
|
9768
|
+
context.report({
|
|
9769
|
+
fix: (fixer) => fixer.replaceTextRange(
|
|
9770
|
+
[openBrace.range[1], firstMember.range[0]],
|
|
9771
|
+
"\n" + " ".repeat(firstMember.loc.start.column),
|
|
9772
|
+
),
|
|
9773
|
+
message: "No empty line after opening brace in type definition",
|
|
9774
|
+
node: firstMember,
|
|
9775
|
+
});
|
|
9776
|
+
}
|
|
9777
|
+
}
|
|
9778
|
+
|
|
9779
|
+
// Find closing brace
|
|
9780
|
+
const closeBrace = sourceCode.getLastToken(node);
|
|
9781
|
+
|
|
9782
|
+
if (closeBrace && closeBrace.value === "}") {
|
|
9783
|
+
// Check for empty line before closing brace
|
|
9784
|
+
if (closeBrace.loc.start.line - lastMember.loc.end.line > 1) {
|
|
9785
|
+
context.report({
|
|
9786
|
+
fix: (fixer) => fixer.replaceTextRange(
|
|
9787
|
+
[lastMember.range[1], closeBrace.range[0]],
|
|
9788
|
+
"\n" + " ".repeat(closeBrace.loc.start.column),
|
|
9789
|
+
),
|
|
9790
|
+
message: "No empty line before closing brace in type definition",
|
|
9791
|
+
node: lastMember,
|
|
9792
|
+
});
|
|
9793
|
+
}
|
|
9794
|
+
}
|
|
9795
|
+
|
|
9796
|
+
// Check for empty lines between members
|
|
9797
|
+
for (let i = 0; i < node.members.length - 1; i += 1) {
|
|
9798
|
+
const current = node.members[i];
|
|
9799
|
+
const next = node.members[i + 1];
|
|
9800
|
+
|
|
9801
|
+
if (next.loc.start.line - current.loc.end.line > 1) {
|
|
9802
|
+
context.report({
|
|
9803
|
+
fix: (fixer) => fixer.replaceTextRange(
|
|
9804
|
+
[current.range[1], next.range[0]],
|
|
9805
|
+
"\n" + " ".repeat(next.loc.start.column),
|
|
9806
|
+
),
|
|
9807
|
+
message: "No empty lines between type members",
|
|
9808
|
+
node: next,
|
|
9809
|
+
});
|
|
9810
|
+
}
|
|
9811
|
+
}
|
|
9812
|
+
};
|
|
9813
|
+
|
|
9860
9814
|
return {
|
|
9861
9815
|
ArrowFunctionExpression: checkFunctionHandler,
|
|
9862
9816
|
FunctionDeclaration: checkFunctionHandler,
|
|
9863
9817
|
FunctionExpression: checkFunctionHandler,
|
|
9818
|
+
TSTypeLiteral: checkTypeLiteralHandler,
|
|
9864
9819
|
};
|
|
9865
9820
|
},
|
|
9866
9821
|
meta: {
|
|
9867
|
-
docs: { description: "Disallow empty lines in function parameters" },
|
|
9822
|
+
docs: { description: "Disallow empty lines in function parameters and type definitions" },
|
|
9868
9823
|
fixable: "whitespace",
|
|
9869
9824
|
schema: [],
|
|
9870
9825
|
type: "layout",
|
package/package.json
CHANGED