Skip to content

Commit 36c8636

Browse files
committed
fix(regex): match nested statements in declaration files
- https://regex101.com/r/JtvRUt/12 - https://regex101.com/r/8HpMrA/13 - https://regex101.com/r/G7GhEt/8 - https://regex101.com/r/KQEDdZ/16 Signed-off-by: Lexus Drumgold <[email protected]>
1 parent ae2bdd9 commit 36c8636

11 files changed

+241
-3
lines changed

src/__snapshots__/export-aggregate.snap

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,75 @@ exports[`unit:EXPORT_AGGREGATE_REGEX > exports > should match namespace export w
122122
},
123123
}
124124
`;
125+
126+
exports[`unit:EXPORT_AGGREGATE_REGEX > exports > should match nested export statement(s) in declaration file 1`] = `
127+
[
128+
{
129+
"0": "export { default } from './make'",
130+
"1": undefined,
131+
"2": "{ default }",
132+
"3": "./make",
133+
"groups": {
134+
"exports": "{ default }",
135+
"specifier": "./make",
136+
"type": undefined,
137+
},
138+
},
139+
{
140+
"0": "export {
141+
DEFAULTS,
142+
plugin as default,
143+
type Options
144+
} from './plugin'",
145+
"1": undefined,
146+
"2": "{
147+
DEFAULTS,
148+
plugin as default,
149+
type Options
150+
}",
151+
"3": "./plugin",
152+
"groups": {
153+
"exports": "{
154+
DEFAULTS,
155+
plugin as default,
156+
type Options
157+
}",
158+
"specifier": "./plugin",
159+
"type": undefined,
160+
},
161+
},
162+
{
163+
"0": "export type { Config, Result } from './interfaces'",
164+
"1": "type",
165+
"2": "{ Config, Result }",
166+
"3": "./interfaces",
167+
"groups": {
168+
"exports": "{ Config, Result }",
169+
"specifier": "./interfaces",
170+
"type": "type",
171+
},
172+
},
173+
{
174+
"0": "export type { default as Options } from './options'",
175+
"1": "type",
176+
"2": "{ default as Options }",
177+
"3": "./options",
178+
"groups": {
179+
"exports": "{ default as Options }",
180+
"specifier": "./options",
181+
"type": "type",
182+
},
183+
},
184+
{
185+
"0": "export type Foo from '#foo'",
186+
"1": "type",
187+
"2": "Foo",
188+
"3": "#foo",
189+
"groups": {
190+
"exports": "Foo",
191+
"specifier": "#foo",
192+
"type": "type",
193+
},
194+
},
195+
]
196+
`;

src/__snapshots__/export-declaration.snap

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,33 @@ exports[`unit:EXPORT_DECLARATION_REGEX > exports > namespace > should match expo
346346
}
347347
`;
348348

349+
exports[`unit:EXPORT_DECLARATION_REGEX > exports > should match nested export statement(s) in declaration file 1`] = `
350+
[
351+
{
352+
"0": "export declare abstract class Building",
353+
"1": "declare abstract",
354+
"2": "class",
355+
"3": "Building",
356+
"groups": {
357+
"declaration": "class",
358+
"exports": "Building",
359+
"modifiers": "declare abstract",
360+
},
361+
},
362+
{
363+
"0": "export declare class House",
364+
"1": "declare",
365+
"2": "class",
366+
"3": "House",
367+
"groups": {
368+
"declaration": "class",
369+
"exports": "House",
370+
"modifiers": "declare",
371+
},
372+
},
373+
]
374+
`;
375+
349376
exports[`unit:EXPORT_DECLARATION_REGEX > exports > type > should match export declare type [exports] 1`] = `
350377
{
351378
"0": "export declare type Options",

src/__snapshots__/export-default.snap

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,20 @@ exports[`unit:EXPORT_DEFAULT_REGEX > exports > namespace > should match export d
266266
}
267267
`;
268268

269+
exports[`unit:EXPORT_DEFAULT_REGEX > exports > should match nested export statement in declaration file 1`] = `
270+
{
271+
"0": "export default class ClassName",
272+
"1": undefined,
273+
"2": "class",
274+
"3": "ClassName",
275+
"groups": {
276+
"exports": "ClassName",
277+
"kind": "class",
278+
"modifiers": undefined,
279+
},
280+
}
281+
`;
282+
269283
exports[`unit:EXPORT_DEFAULT_REGEX > exports > type > should match export default type [identifier] 1`] = `
270284
{
271285
"0": "export default type Options",

src/__snapshots__/export-list.snap

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,47 @@ exports[`unit:EXPORT_LIST_REGEX > exports > should match named type export(s) in
8686
},
8787
}
8888
`;
89+
90+
exports[`unit:EXPORT_LIST_REGEX > exports > should match nested export statement(s) in declaration file 1`] = `
91+
[
92+
{
93+
"0": "export {
94+
DEFAULTS,
95+
plugin as default,
96+
type Options
97+
}",
98+
"1": undefined,
99+
"2": "{
100+
DEFAULTS,
101+
plugin as default,
102+
type Options
103+
}",
104+
"groups": {
105+
"exports": "{
106+
DEFAULTS,
107+
plugin as default,
108+
type Options
109+
}",
110+
"type": undefined,
111+
},
112+
},
113+
{
114+
"0": "export type { Config, Result }",
115+
"1": "type",
116+
"2": "{ Config, Result }",
117+
"groups": {
118+
"exports": "{ Config, Result }",
119+
"type": "type",
120+
},
121+
},
122+
{
123+
"0": "export type { default as Options }",
124+
"1": "type",
125+
"2": "{ default as Options }",
126+
"groups": {
127+
"exports": "{ default as Options }",
128+
"type": "type",
129+
},
130+
},
131+
]
132+
`;

src/__tests__/export-aggregate.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* @module export-regex/tests/unit/aggregate
44
*/
55

6+
import { omit } from 'radash'
67
import { dedent } from 'ts-dedent'
78
import TEST_SUBJECT from '../export-aggregate'
89

@@ -114,5 +115,29 @@ describe('unit:EXPORT_AGGREGATE_REGEX', () => {
114115
expect(result).to.not.be.null
115116
expect(result).toMatchSnapshot()
116117
})
118+
119+
it('should match nested export statement(s) in declaration file', () => {
120+
// Arrange
121+
const code = dedent`
122+
declare module 'module-name' {
123+
export { default } from './make'
124+
export {
125+
DEFAULTS,
126+
plugin as default,
127+
type Options
128+
} from './plugin'
129+
export type { Config, Result } from './interfaces'
130+
export type { default as Options } from './options'
131+
export type Foo from '#foo'
132+
}
133+
`
134+
135+
// Act
136+
const result = [...code.matchAll(TEST_SUBJECT)]
137+
138+
// Expect
139+
expect(result).to.not.be.empty
140+
expect(result.map(res => omit(res, ['index', 'input']))).toMatchSnapshot()
141+
})
117142
})
118143
})

src/__tests__/export-declaration.spec.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,23 @@ describe('unit:EXPORT_DECLARATION_REGEX', () => {
3030
})
3131

3232
describe('exports', () => {
33+
it('should match nested export statement(s) in declaration file', () => {
34+
// Arrange
35+
const code = dedent`
36+
declare module 'module-name' {
37+
export declare abstract class Building {}
38+
export declare class House extends Building {}
39+
}
40+
`
41+
42+
// Act
43+
const result = [...code.matchAll(TEST_SUBJECT)]
44+
45+
// Expect
46+
expect(result).to.not.be.empty
47+
expect(result.map(res => omit(res, ['index', 'input']))).toMatchSnapshot()
48+
})
49+
3350
describe('class', () => {
3451
it('should match export abstract class [exports]', () => {
3552
// Act

src/__tests__/export-default.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,22 @@ describe('unit:EXPORT_DEFAULT_REGEX', () => {
2929
})
3030

3131
describe('exports', () => {
32+
it('should match nested export statement in declaration file', () => {
33+
// Arrange
34+
const code = dedent`
35+
declare module 'module-name' {
36+
export default class ClassName { /* … */ }
37+
}
38+
`
39+
40+
// Act
41+
const result = TEST_SUBJECT.exec(code)
42+
43+
// Expect
44+
expect(result).to.not.be.null
45+
expect(result).toMatchSnapshot()
46+
})
47+
3248
describe('class', () => {
3349
it('should match export default abstract class [identifier]', () => {
3450
// Act

src/__tests__/export-list.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* @module export-regex/tests/unit/list
44
*/
55

6+
import { omit } from 'radash'
67
import { dedent } from 'ts-dedent'
78
import TEST_SUBJECT from '../export-list'
89

@@ -107,5 +108,27 @@ describe('unit:EXPORT_LIST_REGEX', () => {
107108
expect(result).to.not.be.null
108109
expect(result).toMatchSnapshot()
109110
})
111+
112+
it('should match nested export statement(s) in declaration file', () => {
113+
// Arrange
114+
const code = dedent`
115+
declare module 'module-name' {
116+
export {
117+
DEFAULTS,
118+
plugin as default,
119+
type Options
120+
}
121+
export type { Config, Result }
122+
export type { default as Options }
123+
}
124+
`
125+
126+
// Act
127+
const result = [...code.matchAll(TEST_SUBJECT)]
128+
129+
// Expect
130+
expect(result).to.not.be.empty
131+
expect(result.map(res => omit(res, ['index', 'input']))).toMatchSnapshot()
132+
})
110133
})
111134
})

src/export-aggregate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,6 @@
7171
* @const {RegExp} EXPORT_AGGREGATE_REGEX
7272
*/
7373
const EXPORT_AGGREGATE_REGEX: RegExp =
74-
/(?<=^|[\n;])export(?:(?:\s+(?<type>type)\s*)|\s*)(?<exports>(?:\*(?:\s+as\s+\S+)?)|\S+|(?:{[\w\t\n\r "$'*,./{}-]+?}))\s*from\s*["']\s*(?<specifier>(?:(?<='\s*)[^']*[^\s'](?=\s*'))|(?:(?<="\s*)[^"]*[^\s"](?=\s*")))\s*["']/g
74+
/(?<=^|[\n;](?:[\t ]*(?:\w+ )?)?)export(?:(?:\s+(?<type>type)\s*)|\s*)(?<exports>(?:\*(?:\s+as\s+\S+)?)|\S+|(?:{[\w\t\n\r "$'*,./{}-]+?}))\s*from\s*["']\s*(?<specifier>(?:(?<='\s*)[^']*[^\s'](?=\s*'))|(?:(?<="\s*)[^"]*[^\s"](?=\s*")))\s*["']/g
7575

7676
export default EXPORT_AGGREGATE_REGEX

src/export-declaration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,6 @@
330330
* @const {RegExp} EXPORT_DECLARATION_REGEX
331331
*/
332332
const EXPORT_DECLARATION_REGEX: RegExp =
333-
/(?<=^|[\n;])export\s*(?<modifiers>(?:\s*declare|\s*abstract|\s*async)+)?\s*(?<declaration>class|const +enum|const|enum|function\*?|interface|let|namespace|type(?! *\{)|var)\s+(?<exports>(?:[$_\p{ID_Start}][$\u200C\u200D\p{ID_Continue}]*(?=[\s=:;/({])(?!.*?,))|(?:[\w\t\n\r .,:$'"=-]+)|(?:[{[][\w\t\n\r .,:$'"-]+[}\]]))(?:\s*=\s*[$_\p{ID_Start}][$\u200C\u200D\p{ID_Continue}]*)?/gu
333+
/(?<=^|[\n;](?:[\t ]*(?:\w+ )?)?)export\s*(?<modifiers>(?:\s*declare|\s*abstract|\s*async)+)?\s*(?<declaration>class|const +enum|const|enum|function\*?|interface|let|namespace|type(?! *\{)|var)\s+(?<exports>(?:[$_\p{ID_Start}][$\u200C\u200D\p{ID_Continue}]*(?=[\s=:;/({])(?!.*?,))|(?:[\w\t\n\r .,:$'"=-]+)|(?:[{[][\w\t\n\r .,:$'"-]+[}\]]))(?:\s*=\s*[$_\p{ID_Start}][$\u200C\u200D\p{ID_Continue}]*)?/gu
334334

335335
export default EXPORT_DECLARATION_REGEX

0 commit comments

Comments
 (0)