@unix/eslint 1.1.2 → 1.2.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.
@@ -1,18 +1,13 @@
1
1
  const lineBreakFor = sourceCode => (sourceCode.text.includes('\r\n') ? '\r\n' : '\n')
2
2
 
3
- const LONG_BLOCK_MIN_LINES = 4
4
-
5
3
  const indentationFor = (sourceCode, token) => {
6
4
  const line = sourceCode.lines[token.loc.start.line - 1] ?? ''
7
5
 
8
6
  return line.slice(0, token.loc.start.column)
9
7
  }
10
8
 
11
- const spacingBefore = (sourceCode, token, blankLines) =>
12
- `${lineBreakFor(sourceCode).repeat(blankLines + 1)}${indentationFor(
13
- sourceCode,
14
- token,
15
- )}`
9
+ const spacingBefore = (sourceCode, token) =>
10
+ `${lineBreakFor(sourceCode)}${indentationFor(sourceCode, token)}`
16
11
 
17
12
  const paddingLineSequencesBetween = (sourceCode, leftToken, rightToken) => {
18
13
  const sequences = []
@@ -48,18 +43,36 @@ const hasTokensBetween = (sourceCode, leftToken, rightToken) =>
48
43
  sourceCode.getTokensBetween(leftToken, rightToken, { includeComments: true })
49
44
  .length > 0
50
45
 
51
- const reportPadding = (
46
+ const hasBlockBody = node => {
47
+ if (node.type === 'BlockStatement') return true
48
+ if (node.type === 'FunctionDeclaration') return true
49
+ if (node.type === 'SwitchStatement') return true
50
+ if (node.type === 'TryStatement') return true
51
+ if (node.type === 'IfStatement') {
52
+ if (hasBlockBody(node.consequent)) return true
53
+
54
+ return Boolean(node.alternate && hasBlockBody(node.alternate))
55
+ }
56
+
57
+ return node.body?.type === 'BlockStatement'
58
+ }
59
+
60
+ const isSingleLineStatement = node => node.loc.start.line === node.loc.end.line
61
+
62
+ const isRestrictedStatement = node =>
63
+ isSingleLineStatement(node) && !hasBlockBody(node)
64
+
65
+ const reportUnexpectedBlankLine = (
52
66
  context,
53
67
  sourceCode,
54
- node,
55
- leftToken,
56
- rightToken,
57
- maxBlankLines,
58
- messageId,
68
+ previousStatement,
69
+ nextStatement,
59
70
  ) => {
71
+ const leftToken = sourceCode.getLastToken(previousStatement)
72
+ const rightToken = sourceCode.getFirstToken(nextStatement)
60
73
  const sequences = paddingLineSequencesBetween(sourceCode, leftToken, rightToken)
61
74
 
62
- if (blankLineCount(sequences) <= maxBlankLines) return
75
+ if (blankLineCount(sequences) === 0) return
63
76
 
64
77
  const [firstSequence] = sequences
65
78
 
@@ -69,7 +82,7 @@ const reportPadding = (
69
82
 
70
83
  return fixer.replaceTextRange(
71
84
  [leftToken.range[1], rightToken.range[0]],
72
- spacingBefore(sourceCode, rightToken, maxBlankLines),
85
+ spacingBefore(sourceCode, rightToken),
73
86
  )
74
87
  },
75
88
  loc: {
@@ -79,135 +92,21 @@ const reportPadding = (
79
92
  line: firstSequence.leftToken.loc.end.line + 1,
80
93
  },
81
94
  },
82
- messageId,
83
- node,
95
+ messageId: 'unexpectedBlankLine',
96
+ node: nextStatement,
84
97
  })
85
98
  }
86
99
 
87
- const isReturnStatement = node => node.type === 'ReturnStatement'
88
-
89
- const isCompactReturnIfStatement = node =>
90
- node.type === 'IfStatement' &&
91
- !node.alternate &&
92
- isReturnStatement(node.consequent) &&
93
- node.loc.start.line === node.consequent.loc.start.line
94
-
95
- const isReturnLikeStatement = node =>
96
- isReturnStatement(node) || isCompactReturnIfStatement(node)
97
-
98
- const lineCountFor = node => node.loc.end.line - node.loc.start.line + 1
99
-
100
- const hasBlockBody = node => {
101
- if (node.type === 'BlockStatement') return true
102
- if (node.type === 'FunctionDeclaration') return true
103
- if (node.type === 'SwitchStatement') return true
104
- if (node.type === 'TryStatement') return true
105
- if (node.type === 'IfStatement') {
106
- if (hasBlockBody(node.consequent)) return true
107
-
108
- return Boolean(node.alternate && hasBlockBody(node.alternate))
109
- }
110
-
111
- return node.body?.type === 'BlockStatement'
112
- }
113
-
114
- const isLongBlockStatement = node =>
115
- hasBlockBody(node) && lineCountFor(node) >= LONG_BLOCK_MIN_LINES
116
-
117
- const messageIdForStatementGap = (previousStatement, nextStatement) => {
118
- if (isReturnStatement(previousStatement)) return 'unexpectedBlankLineAfterReturn'
119
- if (isReturnLikeStatement(nextStatement)) return 'tooManyBlankLinesBeforeReturn'
120
-
121
- return 'unexpectedBlankLine'
122
- }
123
-
124
- const maxBlankLinesForStatementGap = (previousStatement, nextStatement) => {
125
- if (isReturnStatement(previousStatement)) return 0
126
- if (isReturnLikeStatement(nextStatement)) return 1
127
- if (isLongBlockStatement(previousStatement)) return 1
128
- if (isLongBlockStatement(nextStatement)) return 1
129
-
130
- return 0
131
- }
132
-
133
- const checkStatementList = (
134
- context,
135
- sourceCode,
136
- node,
137
- statements,
138
- leftToken,
139
- rightToken,
140
- ) => {
141
- if (statements.length === 0) {
142
- reportPadding(
143
- context,
144
- sourceCode,
145
- node,
146
- leftToken,
147
- rightToken,
148
- 0,
149
- 'unexpectedBlankLine',
150
- )
151
- return
152
- }
153
-
154
- const [firstStatement] = statements
155
- const lastStatement = statements[statements.length - 1]
156
-
157
- reportPadding(
158
- context,
159
- sourceCode,
160
- firstStatement,
161
- leftToken,
162
- sourceCode.getFirstToken(firstStatement),
163
- 0,
164
- 'unexpectedBlankLine',
165
- )
166
-
100
+ const checkStatementPairs = (context, sourceCode, statements) => {
167
101
  for (let index = 1; index < statements.length; index += 1) {
168
102
  const previousStatement = statements[index - 1]
169
103
  const nextStatement = statements[index]
170
104
 
171
- reportPadding(
172
- context,
173
- sourceCode,
174
- nextStatement,
175
- sourceCode.getLastToken(previousStatement),
176
- sourceCode.getFirstToken(nextStatement),
177
- maxBlankLinesForStatementGap(previousStatement, nextStatement),
178
- messageIdForStatementGap(previousStatement, nextStatement),
179
- )
180
- }
181
-
182
- reportPadding(
183
- context,
184
- sourceCode,
185
- lastStatement,
186
- sourceCode.getLastToken(lastStatement),
187
- rightToken,
188
- 0,
189
- isReturnStatement(lastStatement)
190
- ? 'unexpectedBlankLineAfterReturn'
191
- : 'unexpectedBlankLine',
192
- )
193
- }
194
-
195
- const caseColonToken = (sourceCode, node) => {
196
- const tokenBeforeConsequent = sourceCode.getTokenBefore(node.consequent[0])
197
-
198
- if (tokenBeforeConsequent?.value === ':') return tokenBeforeConsequent
105
+ if (!isRestrictedStatement(previousStatement)) continue
106
+ if (!isRestrictedStatement(nextStatement)) continue
199
107
 
200
- const firstToken = sourceCode.getFirstToken(node)
201
-
202
- return sourceCode.getTokenAfter(firstToken, {
203
- filter: token => token.value === ':',
204
- })
205
- }
206
-
207
- const caseEndToken = (sourceCode, node) => {
208
- const lastStatement = node.consequent[node.consequent.length - 1]
209
-
210
- return sourceCode.getTokenAfter(sourceCode.getLastToken(lastStatement))
108
+ reportUnexpectedBlankLine(context, sourceCode, previousStatement, nextStatement)
109
+ }
211
110
  }
212
111
 
213
112
  const functionBlankLines = {
@@ -215,14 +114,12 @@ const functionBlankLines = {
215
114
  type: 'layout',
216
115
  docs: {
217
116
  description:
218
- 'Disallow extra blank lines in functions except before return statements',
117
+ 'Disallow blank lines between adjacent single-line non-block statements',
219
118
  },
220
119
  fixable: 'whitespace',
221
120
  messages: {
222
- tooManyBlankLinesBeforeReturn:
223
- 'Return statements may have at most one blank line above them.',
224
- unexpectedBlankLine: 'Unexpected blank line inside function.',
225
- unexpectedBlankLineAfterReturn: 'Unexpected blank line after return.',
121
+ unexpectedBlankLine:
122
+ 'Unexpected blank line between adjacent single-line statements.',
226
123
  },
227
124
  schema: [],
228
125
  },
@@ -246,14 +143,7 @@ const functionBlankLines = {
246
143
  BlockStatement(node) {
247
144
  if (!isInsideFunction()) return
248
145
 
249
- checkStatementList(
250
- context,
251
- sourceCode,
252
- node,
253
- node.body,
254
- sourceCode.getFirstToken(node),
255
- sourceCode.getLastToken(node),
256
- )
146
+ checkStatementPairs(context, sourceCode, node.body)
257
147
  },
258
148
  FunctionDeclaration: enterFunction,
259
149
  'FunctionDeclaration:exit': exitFunction,
@@ -261,16 +151,8 @@ const functionBlankLines = {
261
151
  'FunctionExpression:exit': exitFunction,
262
152
  SwitchCase(node) {
263
153
  if (!isInsideFunction()) return
264
- if (node.consequent.length === 0) return
265
-
266
- checkStatementList(
267
- context,
268
- sourceCode,
269
- node,
270
- node.consequent,
271
- caseColonToken(sourceCode, node),
272
- caseEndToken(sourceCode, node),
273
- )
154
+
155
+ checkStatementPairs(context, sourceCode, node.consequent)
274
156
  },
275
157
  }
276
158
  },
package/configs/ts.js CHANGED
@@ -73,13 +73,6 @@ const classMemberOrder = [
73
73
  ],
74
74
  ]
75
75
 
76
- const recommendedTypeChecked = tseslint.configs.recommendedTypeChecked.map(
77
- config => ({
78
- ...config,
79
- files: config.files ?? tsFiles,
80
- }),
81
- )
82
-
83
76
  const withTsFiles = config => ({
84
77
  ...config,
85
78
  files: tsFiles,
@@ -91,7 +84,6 @@ export default tseslint.config(
91
84
  ...eslint.configs.recommended,
92
85
  files: tsFiles,
93
86
  },
94
- ...recommendedTypeChecked,
95
87
  {
96
88
  files: tsFiles,
97
89
  languageOptions: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unix/eslint",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "description": "ESLint config for all @unix projects.",
5
5
  "type": "module",
6
6
  "main": "index.js",