@mui/internal-code-infra 0.0.4-canary.73 → 0.0.4-canary.75
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/package.json +7 -5
- package/src/brokenLinksChecker/crawlWorker.mjs +23 -0
- package/src/cli/cmdPublish.mjs +32 -3
- package/src/brokenLinksChecker/__fixtures__/static-site/broken-links.html +0 -20
- package/src/brokenLinksChecker/__fixtures__/static-site/broken-targets.html +0 -22
- package/src/brokenLinksChecker/__fixtures__/static-site/example.md +0 -20
- package/src/brokenLinksChecker/__fixtures__/static-site/external-links.html +0 -21
- package/src/brokenLinksChecker/__fixtures__/static-site/ignored-page.html +0 -17
- package/src/brokenLinksChecker/__fixtures__/static-site/index.html +0 -29
- package/src/brokenLinksChecker/__fixtures__/static-site/invalid-html.html +0 -15
- package/src/brokenLinksChecker/__fixtures__/static-site/known-targets.json +0 -5
- package/src/brokenLinksChecker/__fixtures__/static-site/nested/page.html +0 -21
- package/src/brokenLinksChecker/__fixtures__/static-site/orphaned-page.html +0 -20
- package/src/brokenLinksChecker/__fixtures__/static-site/page-with-api-links.html +0 -20
- package/src/brokenLinksChecker/__fixtures__/static-site/page-with-custom-targets.html +0 -24
- package/src/brokenLinksChecker/__fixtures__/static-site/page-with-ignored-content.html +0 -28
- package/src/brokenLinksChecker/__fixtures__/static-site/page-with-known-target-links.html +0 -19
- package/src/brokenLinksChecker/__fixtures__/static-site/unclosed-tags.html +0 -1
- package/src/brokenLinksChecker/__fixtures__/static-site/valid.html +0 -20
- package/src/brokenLinksChecker/__fixtures__/static-site/with-anchors.html +0 -31
- package/src/brokenLinksChecker/index.test.ts +0 -301
- package/src/changelog/categorizeCommits.test.ts +0 -319
- package/src/changelog/filterCommits.test.ts +0 -363
- package/src/changelog/parseCommitLabels.test.ts +0 -509
- package/src/changelog/renderChangelog.test.ts +0 -378
- package/src/changelog/sortSections.test.ts +0 -199
- package/src/cli/cmdVale.test.mjs +0 -644
- package/src/eslint/mui/rules/add-undef-to-optional.test.mjs +0 -361
- package/src/eslint/mui/rules/consistent-production-guard.test.mjs +0 -162
- package/src/eslint/mui/rules/disallow-active-elements-as-key-event-target.test.mjs +0 -66
- package/src/eslint/mui/rules/disallow-react-api-in-server-components.test.mjs +0 -305
- package/src/eslint/mui/rules/docgen-ignore-before-comment.test.mjs +0 -52
- package/src/eslint/mui/rules/flatten-parentheses.test.mjs +0 -245
- package/src/eslint/mui/rules/mui-name-matches-component-name.test.mjs +0 -247
- package/src/eslint/mui/rules/no-empty-box.test.mjs +0 -40
- package/src/eslint/mui/rules/no-floating-cleanup.test.mjs +0 -141
- package/src/eslint/mui/rules/no-guarded-throw.test.mjs +0 -206
- package/src/eslint/mui/rules/no-presentation-role.test.mjs +0 -33
- package/src/eslint/mui/rules/no-styled-box.test.mjs +0 -73
- package/src/eslint/mui/rules/require-dev-wrapper.test.mjs +0 -265
- package/src/eslint/mui/rules/rules-of-use-theme-variants.test.mjs +0 -149
- package/src/eslint/mui/rules/straight-quotes.test.mjs +0 -67
- package/src/remark/firstBlockHeading.test.mjs +0 -107
- package/src/remark/gitDiff.test.mjs +0 -45
- package/src/remark/noSpaceInLinks.test.mjs +0 -22
- package/src/remark/straightQuotes.test.mjs +0 -25
- package/src/remark/tableAlignment.test.mjs +0 -28
- package/src/remark/terminalLanguage.test.mjs +0 -17
- package/src/utils/build.test.mjs +0 -1263
- package/src/utils/pnpm.test.mjs +0 -731
- package/src/utils/template.test.mjs +0 -133
- package/src/utils/typescript.test.mjs +0 -341
|
@@ -1,305 +0,0 @@
|
|
|
1
|
-
import eslint from 'eslint';
|
|
2
|
-
import parser from '@typescript-eslint/parser';
|
|
3
|
-
import rule from './disallow-react-api-in-server-components.mjs';
|
|
4
|
-
|
|
5
|
-
const ruleTester = new eslint.RuleTester({
|
|
6
|
-
languageOptions: {
|
|
7
|
-
parser,
|
|
8
|
-
parserOptions: {
|
|
9
|
-
ecmaFeatures: { jsx: true },
|
|
10
|
-
},
|
|
11
|
-
},
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
ruleTester.run('disallow-react-api-in-server-components', rule, {
|
|
15
|
-
valid: [
|
|
16
|
-
// Files with 'use client' directive are allowed to use React APIs
|
|
17
|
-
{
|
|
18
|
-
name: 'React.useState with use client directive',
|
|
19
|
-
code: `'use client';
|
|
20
|
-
React.useState();`,
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
name: 'React.useEffect with use client directive',
|
|
24
|
-
code: `'use client';
|
|
25
|
-
React.useEffect(() => {});`,
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
name: 'React.useContext with use client directive',
|
|
29
|
-
code: `'use client';
|
|
30
|
-
React.useContext(MyContext);`,
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
name: 'React.useRef with use client directive',
|
|
34
|
-
code: `'use client';
|
|
35
|
-
React.useRef();`,
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
name: 'import useState with use client directive',
|
|
39
|
-
code: `'use client';
|
|
40
|
-
import { useState } from 'react';`,
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
name: 'import useContext with use client directive',
|
|
44
|
-
code: `'use client';
|
|
45
|
-
import { useContext } from 'react';`,
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
name: 'import useRef with use client directive',
|
|
49
|
-
code: `'use client';
|
|
50
|
-
import { useRef } from 'react';`,
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
name: 'import useIsoLayoutEffect with use client directive',
|
|
54
|
-
code: `'use client';
|
|
55
|
-
import { useIsoLayoutEffect } from '@mui/utils';`,
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
name: 'useIsoLayoutEffect call with use client directive',
|
|
59
|
-
code: `'use client';
|
|
60
|
-
useIsoLayoutEffect(() => {});`,
|
|
61
|
-
},
|
|
62
|
-
// APIs not in the forbidden list are allowed
|
|
63
|
-
{
|
|
64
|
-
name: 'React.memo is allowed',
|
|
65
|
-
code: `React.memo(() => {});`,
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
name: 'React.forwardRef is allowed',
|
|
69
|
-
code: `React.forwardRef(() => {});`,
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
name: 'import useMemo is allowed',
|
|
73
|
-
code: `import { useMemo } from 'react';`,
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
name: 'custom hook is allowed',
|
|
77
|
-
code: `import { useCustomHook } from './hooks';`,
|
|
78
|
-
},
|
|
79
|
-
],
|
|
80
|
-
invalid: [
|
|
81
|
-
// React.* API calls without 'use client' directive
|
|
82
|
-
{
|
|
83
|
-
name: 'React.useState without use client directive',
|
|
84
|
-
code: `React.useState();`,
|
|
85
|
-
errors: [
|
|
86
|
-
{
|
|
87
|
-
message:
|
|
88
|
-
"Using 'React.useState' is forbidden if the file doesn't have a 'use client' directive.",
|
|
89
|
-
},
|
|
90
|
-
],
|
|
91
|
-
output: `'use client';
|
|
92
|
-
React.useState();`,
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
name: 'React.useEffect without use client directive',
|
|
96
|
-
code: `React.useEffect(() => {});`,
|
|
97
|
-
errors: [
|
|
98
|
-
{
|
|
99
|
-
message:
|
|
100
|
-
"Using 'React.useEffect' is forbidden if the file doesn't have a 'use client' directive.",
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
|
-
output: `'use client';
|
|
104
|
-
React.useEffect(() => {});`,
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
name: 'React.useContext without use client directive',
|
|
108
|
-
code: `React.useContext(MyContext);`,
|
|
109
|
-
errors: [
|
|
110
|
-
{
|
|
111
|
-
message:
|
|
112
|
-
"Using 'React.useContext' is forbidden if the file doesn't have a 'use client' directive.",
|
|
113
|
-
},
|
|
114
|
-
],
|
|
115
|
-
output: `'use client';
|
|
116
|
-
React.useContext(MyContext);`,
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
name: 'React.useRef without use client directive',
|
|
120
|
-
code: `React.useRef();`,
|
|
121
|
-
errors: [
|
|
122
|
-
{
|
|
123
|
-
message:
|
|
124
|
-
"Using 'React.useRef' is forbidden if the file doesn't have a 'use client' directive.",
|
|
125
|
-
},
|
|
126
|
-
],
|
|
127
|
-
output: `'use client';
|
|
128
|
-
React.useRef();`,
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
name: 'React.useLayoutEffect without use client directive',
|
|
132
|
-
code: `React.useLayoutEffect(() => {});`,
|
|
133
|
-
errors: [
|
|
134
|
-
{
|
|
135
|
-
message:
|
|
136
|
-
"Using 'React.useLayoutEffect' is forbidden if the file doesn't have a 'use client' directive.",
|
|
137
|
-
},
|
|
138
|
-
],
|
|
139
|
-
output: `'use client';
|
|
140
|
-
React.useLayoutEffect(() => {});`,
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
name: 'React.useReducer without use client directive',
|
|
144
|
-
code: `React.useReducer(reducer, initialState);`,
|
|
145
|
-
errors: [
|
|
146
|
-
{
|
|
147
|
-
message:
|
|
148
|
-
"Using 'React.useReducer' is forbidden if the file doesn't have a 'use client' directive.",
|
|
149
|
-
},
|
|
150
|
-
],
|
|
151
|
-
output: `'use client';
|
|
152
|
-
React.useReducer(reducer, initialState);`,
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
name: 'React.useTransition without use client directive',
|
|
156
|
-
code: `React.useTransition();`,
|
|
157
|
-
errors: [
|
|
158
|
-
{
|
|
159
|
-
message:
|
|
160
|
-
"Using 'React.useTransition' is forbidden if the file doesn't have a 'use client' directive.",
|
|
161
|
-
},
|
|
162
|
-
],
|
|
163
|
-
output: `'use client';
|
|
164
|
-
React.useTransition();`,
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
name: 'React.createContext without use client directive',
|
|
168
|
-
code: `React.createContext();`,
|
|
169
|
-
errors: [
|
|
170
|
-
{
|
|
171
|
-
message:
|
|
172
|
-
"Using 'React.createContext' is forbidden if the file doesn't have a 'use client' directive.",
|
|
173
|
-
},
|
|
174
|
-
],
|
|
175
|
-
output: `'use client';
|
|
176
|
-
React.createContext();`,
|
|
177
|
-
},
|
|
178
|
-
// Named imports from 'react' without 'use client' directive
|
|
179
|
-
{
|
|
180
|
-
name: 'import useState without use client directive',
|
|
181
|
-
code: `import { useState } from 'react';`,
|
|
182
|
-
errors: [
|
|
183
|
-
{
|
|
184
|
-
message:
|
|
185
|
-
"Using 'useState' is forbidden if the file doesn't have a 'use client' directive.",
|
|
186
|
-
},
|
|
187
|
-
],
|
|
188
|
-
output: `'use client';
|
|
189
|
-
import { useState } from 'react';`,
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
name: 'import useContext without use client directive',
|
|
193
|
-
code: `import { useContext } from 'react';`,
|
|
194
|
-
errors: [
|
|
195
|
-
{
|
|
196
|
-
message:
|
|
197
|
-
"Using 'useContext' is forbidden if the file doesn't have a 'use client' directive.",
|
|
198
|
-
},
|
|
199
|
-
],
|
|
200
|
-
output: `'use client';
|
|
201
|
-
import { useContext } from 'react';`,
|
|
202
|
-
},
|
|
203
|
-
{
|
|
204
|
-
name: 'import useRef without use client directive',
|
|
205
|
-
code: `import { useRef } from 'react';`,
|
|
206
|
-
errors: [
|
|
207
|
-
{
|
|
208
|
-
message: "Using 'useRef' is forbidden if the file doesn't have a 'use client' directive.",
|
|
209
|
-
},
|
|
210
|
-
],
|
|
211
|
-
output: `'use client';
|
|
212
|
-
import { useRef } from 'react';`,
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
name: 'import multiple React APIs without use client directive',
|
|
216
|
-
code: `import { useState, useEffect } from 'react';`,
|
|
217
|
-
errors: [
|
|
218
|
-
{
|
|
219
|
-
message:
|
|
220
|
-
"Using 'useState' is forbidden if the file doesn't have a 'use client' directive.",
|
|
221
|
-
},
|
|
222
|
-
{
|
|
223
|
-
message:
|
|
224
|
-
"Using 'useEffect' is forbidden if the file doesn't have a 'use client' directive.",
|
|
225
|
-
},
|
|
226
|
-
],
|
|
227
|
-
output: `'use client';
|
|
228
|
-
import { useState, useEffect } from 'react';`,
|
|
229
|
-
},
|
|
230
|
-
// Forbidden APIs (useIsoLayoutEffect)
|
|
231
|
-
{
|
|
232
|
-
name: 'import useIsoLayoutEffect without use client directive',
|
|
233
|
-
code: `import { useIsoLayoutEffect } from '@mui/utils';`,
|
|
234
|
-
errors: [
|
|
235
|
-
{
|
|
236
|
-
message:
|
|
237
|
-
"Using 'useIsoLayoutEffect' is forbidden if the file doesn't have a 'use client' directive.",
|
|
238
|
-
},
|
|
239
|
-
],
|
|
240
|
-
output: `'use client';
|
|
241
|
-
import { useIsoLayoutEffect } from '@mui/utils';`,
|
|
242
|
-
},
|
|
243
|
-
{
|
|
244
|
-
name: 'import useIsoLayoutEffect as default without use client directive',
|
|
245
|
-
code: `import useIsoLayoutEffect from '@mui/utils/useIsoLayoutEffect';`,
|
|
246
|
-
errors: [
|
|
247
|
-
{
|
|
248
|
-
message:
|
|
249
|
-
"Using 'useIsoLayoutEffect' is forbidden if the file doesn't have a 'use client' directive.",
|
|
250
|
-
},
|
|
251
|
-
],
|
|
252
|
-
output: `'use client';
|
|
253
|
-
import useIsoLayoutEffect from '@mui/utils/useIsoLayoutEffect';`,
|
|
254
|
-
},
|
|
255
|
-
{
|
|
256
|
-
name: 'useIsoLayoutEffect call without use client directive',
|
|
257
|
-
code: `useIsoLayoutEffect(() => {});`,
|
|
258
|
-
errors: [
|
|
259
|
-
{
|
|
260
|
-
message:
|
|
261
|
-
"Using 'useIsoLayoutEffect' is forbidden if the file doesn't have a 'use client' directive.",
|
|
262
|
-
},
|
|
263
|
-
],
|
|
264
|
-
output: `'use client';
|
|
265
|
-
useIsoLayoutEffect(() => {});`,
|
|
266
|
-
},
|
|
267
|
-
// No autofix for 'use server' files
|
|
268
|
-
{
|
|
269
|
-
name: 'React.useState in use server file (no autofix)',
|
|
270
|
-
code: `'use server';
|
|
271
|
-
React.useState();`,
|
|
272
|
-
errors: [
|
|
273
|
-
{
|
|
274
|
-
message:
|
|
275
|
-
"Using 'React.useState' is forbidden if the file doesn't have a 'use client' directive.",
|
|
276
|
-
},
|
|
277
|
-
],
|
|
278
|
-
output: null,
|
|
279
|
-
},
|
|
280
|
-
{
|
|
281
|
-
name: 'import useState in use server file (no autofix)',
|
|
282
|
-
code: `'use server';
|
|
283
|
-
import { useState } from 'react';`,
|
|
284
|
-
errors: [
|
|
285
|
-
{
|
|
286
|
-
message:
|
|
287
|
-
"Using 'useState' is forbidden if the file doesn't have a 'use client' directive.",
|
|
288
|
-
},
|
|
289
|
-
],
|
|
290
|
-
output: null,
|
|
291
|
-
},
|
|
292
|
-
{
|
|
293
|
-
name: 'import useIsoLayoutEffect in use server file (no autofix)',
|
|
294
|
-
code: `'use server';
|
|
295
|
-
import { useIsoLayoutEffect } from '@mui/utils';`,
|
|
296
|
-
errors: [
|
|
297
|
-
{
|
|
298
|
-
message:
|
|
299
|
-
"Using 'useIsoLayoutEffect' is forbidden if the file doesn't have a 'use client' directive.",
|
|
300
|
-
},
|
|
301
|
-
],
|
|
302
|
-
output: null,
|
|
303
|
-
},
|
|
304
|
-
],
|
|
305
|
-
});
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import eslint from 'eslint';
|
|
2
|
-
import parser from '@typescript-eslint/parser';
|
|
3
|
-
import rule from './docgen-ignore-before-comment.mjs';
|
|
4
|
-
|
|
5
|
-
const ruleTester = new eslint.RuleTester({
|
|
6
|
-
languageOptions: {
|
|
7
|
-
parser,
|
|
8
|
-
},
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
ruleTester.run('ignore-before-comment', rule, {
|
|
12
|
-
valid: [
|
|
13
|
-
'\n/**\n * @ignore\n */\n',
|
|
14
|
-
'\n/**\n * @ignore\n * Comment.\n */\n',
|
|
15
|
-
'\n/**\n * @ignore\n * Multi-line\n * comment.\n */\n',
|
|
16
|
-
'\n /**\n * @ignore\n * Indented\n * multi-line\n * comment.\n */\n',
|
|
17
|
-
],
|
|
18
|
-
invalid: [
|
|
19
|
-
{
|
|
20
|
-
code: '\n/**\n * Comment.\n * @ignore\n */\n',
|
|
21
|
-
errors: [
|
|
22
|
-
{
|
|
23
|
-
message: '@ignore should be at the beginning of a block comment.',
|
|
24
|
-
},
|
|
25
|
-
],
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
code: '\n /**\n * Multi-line\n * comment.\n * @ignore\n */\n',
|
|
29
|
-
errors: [
|
|
30
|
-
{
|
|
31
|
-
message: '@ignore should be at the beginning of a block comment.',
|
|
32
|
-
},
|
|
33
|
-
],
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
code: '\n /**\n * Multi-line\n * @ignore\n * comment.\n */\n',
|
|
37
|
-
errors: [
|
|
38
|
-
{
|
|
39
|
-
message: '@ignore should be at the beginning of a block comment.',
|
|
40
|
-
},
|
|
41
|
-
],
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
code: '\n /**\n * Indented\n * multi-line\n * comment.\n * @ignore\n */\n',
|
|
45
|
-
errors: [
|
|
46
|
-
{
|
|
47
|
-
message: '@ignore should be at the beginning of a block comment.',
|
|
48
|
-
},
|
|
49
|
-
],
|
|
50
|
-
},
|
|
51
|
-
],
|
|
52
|
-
});
|
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
import { RuleTester } from '@typescript-eslint/rule-tester';
|
|
2
|
-
import TSESlintParser from '@typescript-eslint/parser';
|
|
3
|
-
import rule from './flatten-parentheses.mjs';
|
|
4
|
-
|
|
5
|
-
const ruleTester = new RuleTester({
|
|
6
|
-
languageOptions: {
|
|
7
|
-
parser: TSESlintParser,
|
|
8
|
-
},
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
ruleTester.run('flatten-parentheses', rule, {
|
|
12
|
-
valid: [
|
|
13
|
-
// Simple union without parentheses
|
|
14
|
-
`type T = 1 | 2 | 3;`,
|
|
15
|
-
|
|
16
|
-
// Simple intersection without parentheses
|
|
17
|
-
`type T = A & B & C;`,
|
|
18
|
-
|
|
19
|
-
// Parentheses around single type (not in union/intersection context)
|
|
20
|
-
`type T = (string);`,
|
|
21
|
-
|
|
22
|
-
// Parentheses needed for precedence (intersection inside union)
|
|
23
|
-
`type T = (A & B) | C;`,
|
|
24
|
-
|
|
25
|
-
// Parentheses needed for precedence (union inside intersection)
|
|
26
|
-
`type T = (A | B) & C;`,
|
|
27
|
-
|
|
28
|
-
// Complex nested structure where parentheses change meaning
|
|
29
|
-
`type T = (A | B) & (C | D);`,
|
|
30
|
-
|
|
31
|
-
// Function types where parentheses are needed
|
|
32
|
-
`type T = (() => void) | string;`,
|
|
33
|
-
|
|
34
|
-
// Array types
|
|
35
|
-
`type T = (string | number)[];`,
|
|
36
|
-
|
|
37
|
-
// Generic types
|
|
38
|
-
`type T = Promise<string | number>;`,
|
|
39
|
-
|
|
40
|
-
// Mixed operators - parentheses are needed
|
|
41
|
-
`type T = A | (B & C);`,
|
|
42
|
-
`type T = (A | B) & (C | D) | E;`,
|
|
43
|
-
],
|
|
44
|
-
invalid: [
|
|
45
|
-
// Basic union flattening - example from the problem statement
|
|
46
|
-
{
|
|
47
|
-
code: `type T = (1 | 2 | 3) | 4;`,
|
|
48
|
-
output: `type T = 1 | 2 | 3 | 4;`,
|
|
49
|
-
errors: [
|
|
50
|
-
{
|
|
51
|
-
messageId: 'flattenParentheses',
|
|
52
|
-
line: 1,
|
|
53
|
-
column: 11,
|
|
54
|
-
},
|
|
55
|
-
],
|
|
56
|
-
},
|
|
57
|
-
|
|
58
|
-
// Union on the right side
|
|
59
|
-
{
|
|
60
|
-
code: `type T = 1 | (2 | 3 | 4);`,
|
|
61
|
-
output: `type T = 1 | 2 | 3 | 4;`,
|
|
62
|
-
errors: [
|
|
63
|
-
{
|
|
64
|
-
messageId: 'flattenParentheses',
|
|
65
|
-
line: 1,
|
|
66
|
-
},
|
|
67
|
-
],
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
// Multiple parenthesized unions
|
|
71
|
-
{
|
|
72
|
-
code: `type T = (1 | 2) | (3 | 4);`,
|
|
73
|
-
output: `type T = 1 | 2 | 3 | 4;`,
|
|
74
|
-
errors: [
|
|
75
|
-
{
|
|
76
|
-
messageId: 'flattenParentheses',
|
|
77
|
-
line: 1,
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
messageId: 'flattenParentheses',
|
|
81
|
-
line: 1,
|
|
82
|
-
},
|
|
83
|
-
],
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
// Intersection flattening
|
|
87
|
-
{
|
|
88
|
-
code: `type T = (A & B & C) & D;`,
|
|
89
|
-
output: `type T = A & B & C & D;`,
|
|
90
|
-
errors: [
|
|
91
|
-
{
|
|
92
|
-
messageId: 'flattenParentheses',
|
|
93
|
-
line: 1,
|
|
94
|
-
},
|
|
95
|
-
],
|
|
96
|
-
},
|
|
97
|
-
|
|
98
|
-
// Intersection on the right
|
|
99
|
-
{
|
|
100
|
-
code: `type T = A & (B & C & D);`,
|
|
101
|
-
output: `type T = A & B & C & D;`,
|
|
102
|
-
errors: [
|
|
103
|
-
{
|
|
104
|
-
messageId: 'flattenParentheses',
|
|
105
|
-
line: 1,
|
|
106
|
-
},
|
|
107
|
-
],
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
// Multiple parenthesized intersections
|
|
111
|
-
{
|
|
112
|
-
code: `type T = (A & B) & (C & D);`,
|
|
113
|
-
output: `type T = A & B & C & D;`,
|
|
114
|
-
errors: [
|
|
115
|
-
{
|
|
116
|
-
messageId: 'flattenParentheses',
|
|
117
|
-
line: 1,
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
messageId: 'flattenParentheses',
|
|
121
|
-
line: 1,
|
|
122
|
-
},
|
|
123
|
-
],
|
|
124
|
-
},
|
|
125
|
-
|
|
126
|
-
// With type aliases
|
|
127
|
-
{
|
|
128
|
-
code: `type Union = (string | number) | boolean;`,
|
|
129
|
-
output: `type Union = string | number | boolean;`,
|
|
130
|
-
errors: [
|
|
131
|
-
{
|
|
132
|
-
messageId: 'flattenParentheses',
|
|
133
|
-
line: 1,
|
|
134
|
-
},
|
|
135
|
-
],
|
|
136
|
-
},
|
|
137
|
-
|
|
138
|
-
// In type parameters
|
|
139
|
-
{
|
|
140
|
-
code: `type T<U> = (U | null) | undefined;`,
|
|
141
|
-
output: `type T<U> = U | null | undefined;`,
|
|
142
|
-
errors: [
|
|
143
|
-
{
|
|
144
|
-
messageId: 'flattenParentheses',
|
|
145
|
-
line: 1,
|
|
146
|
-
},
|
|
147
|
-
],
|
|
148
|
-
},
|
|
149
|
-
|
|
150
|
-
// With whitespace (trailing space left for Prettier to clean up)
|
|
151
|
-
{
|
|
152
|
-
code: `type T = ( A | B ) | C;`,
|
|
153
|
-
output: `type T = A | B | C;`,
|
|
154
|
-
errors: [
|
|
155
|
-
{
|
|
156
|
-
messageId: 'flattenParentheses',
|
|
157
|
-
line: 1,
|
|
158
|
-
},
|
|
159
|
-
],
|
|
160
|
-
},
|
|
161
|
-
|
|
162
|
-
// Nested unions - multiple fix passes needed due to overlapping ranges
|
|
163
|
-
{
|
|
164
|
-
code: `type T = ((A | B) | C) | D;`,
|
|
165
|
-
output: [`type T = (A | B) | C | D;`, `type T = A | B | C | D;`],
|
|
166
|
-
errors: [
|
|
167
|
-
{
|
|
168
|
-
messageId: 'flattenParentheses',
|
|
169
|
-
line: 1,
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
messageId: 'flattenParentheses',
|
|
173
|
-
line: 1,
|
|
174
|
-
},
|
|
175
|
-
],
|
|
176
|
-
},
|
|
177
|
-
|
|
178
|
-
// Complex type names
|
|
179
|
-
{
|
|
180
|
-
code: `type Result = (Success<Data> | Error<Message>) | Loading;`,
|
|
181
|
-
output: `type Result = Success<Data> | Error<Message> | Loading;`,
|
|
182
|
-
errors: [
|
|
183
|
-
{
|
|
184
|
-
messageId: 'flattenParentheses',
|
|
185
|
-
line: 1,
|
|
186
|
-
},
|
|
187
|
-
],
|
|
188
|
-
},
|
|
189
|
-
|
|
190
|
-
// Multiline union (Prettier cleans up extra whitespace)
|
|
191
|
-
{
|
|
192
|
-
code: `type T = (\n A | B\n) | C;`,
|
|
193
|
-
output: `type T = A | B\n | C;`,
|
|
194
|
-
errors: [
|
|
195
|
-
{
|
|
196
|
-
messageId: 'flattenParentheses',
|
|
197
|
-
},
|
|
198
|
-
],
|
|
199
|
-
},
|
|
200
|
-
|
|
201
|
-
// Leading block comment inside parentheses - preserved in output
|
|
202
|
-
{
|
|
203
|
-
code: `type T = (/* comment */ A | B) | C;`,
|
|
204
|
-
output: `type T = /* comment */ A | B | C;`,
|
|
205
|
-
errors: [
|
|
206
|
-
{
|
|
207
|
-
messageId: 'flattenParentheses',
|
|
208
|
-
},
|
|
209
|
-
],
|
|
210
|
-
},
|
|
211
|
-
|
|
212
|
-
// Trailing block comment inside parentheses - preserved in output
|
|
213
|
-
{
|
|
214
|
-
code: `type T = (A | B /* comment */) | C;`,
|
|
215
|
-
output: `type T = A | B /* comment */ | C;`,
|
|
216
|
-
errors: [
|
|
217
|
-
{
|
|
218
|
-
messageId: 'flattenParentheses',
|
|
219
|
-
},
|
|
220
|
-
],
|
|
221
|
-
},
|
|
222
|
-
|
|
223
|
-
// Trailing line comment - newline preserved so | C continues on next line
|
|
224
|
-
{
|
|
225
|
-
code: `type T = (A | B // comment\n) | C;`,
|
|
226
|
-
output: `type T = A | B // comment\n | C;`,
|
|
227
|
-
errors: [
|
|
228
|
-
{
|
|
229
|
-
messageId: 'flattenParentheses',
|
|
230
|
-
},
|
|
231
|
-
],
|
|
232
|
-
},
|
|
233
|
-
|
|
234
|
-
// Multiline union with leading pipes inside parentheses
|
|
235
|
-
{
|
|
236
|
-
code: 'type T =\n | (\n | boolean\n | string\n )\n | undefined;',
|
|
237
|
-
output: 'type T =\n | boolean\n | string\n \n | undefined;',
|
|
238
|
-
errors: [
|
|
239
|
-
{
|
|
240
|
-
messageId: 'flattenParentheses',
|
|
241
|
-
},
|
|
242
|
-
],
|
|
243
|
-
},
|
|
244
|
-
],
|
|
245
|
-
});
|