forked from cartant/eslint-etc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
from-fixture.ts
115 lines (109 loc) · 3.04 KB
/
from-fixture.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/**
* @license Use of this source code is governed by an MIT-style license that
* can be found in the LICENSE file at https://github.com/cartant/eslint-etc
*/
import { TSESLint as eslint } from "@typescript-eslint/experimental-utils";
export function fromFixture<TMessageIds extends string>(
fixture: string,
invalidTestCase?: {
output?: string;
suggestions?:
| readonly eslint.SuggestionOutput<TMessageIds>[]
| null
| undefined;
}
): eslint.InvalidTestCase<TMessageIds, never>;
export function fromFixture<
TMessageIds extends string,
TOptions extends readonly unknown[]
>(
fixture: string,
invalidTestCase: Omit<
eslint.InvalidTestCase<TMessageIds, TOptions>,
"code" | "errors"
> & {
suggestions?:
| readonly eslint.SuggestionOutput<TMessageIds>[]
| null
| undefined;
}
): eslint.InvalidTestCase<TMessageIds, TOptions>;
export function fromFixture<
TMessageIds extends string,
TOptions extends readonly unknown[]
>(
fixture: string,
invalidTestCase: Omit<
eslint.InvalidTestCase<TMessageIds, TOptions>,
"code" | "errors"
> & {
suggestions?:
| readonly eslint.SuggestionOutput<TMessageIds>[]
| null
| undefined;
} = {}
): eslint.InvalidTestCase<TMessageIds, TOptions> {
const { suggestions, ...rest } = invalidTestCase;
return {
...rest,
...parseFixture(fixture, suggestions),
};
}
function getSuggestions<TMessageIds extends string>(
suggestions:
| readonly eslint.SuggestionOutput<TMessageIds>[]
| null
| undefined,
indices: string | undefined
) {
if (!suggestions || indices === "") {
return {};
}
if (indices === undefined) {
return { suggestions } as const;
}
return {
suggestions: indices
.split(/\s+/)
.map((index) => suggestions[Number.parseInt(index, 10)]),
} as const;
}
function parseFixture<TMessageIds extends string>(
fixture: string,
suggestions:
| readonly eslint.SuggestionOutput<TMessageIds>[]
| null
| undefined
) {
const errorRegExp =
/^(?<indent>\s*)(?<error>~+)\s*\[(?<id>\w+)\s*(?<data>.*?)(?:\s*suggest\s*(?<indices>[\d\s]*))?\]\s*$/;
const lines: string[] = [];
const errors: eslint.TestCaseError<TMessageIds>[] = [];
fixture.split("\n").forEach((line) => {
const match = line.match(errorRegExp);
if (match?.groups) {
const column = match.groups.indent.length + 1;
const endColumn = column + match.groups.error.length;
const { length } = lines;
errors.push({
column,
data: JSON.parse(match.groups.data || "{}"),
endColumn,
endLine: length,
line: length,
messageId: match.groups.id as TMessageIds,
// TODO: Remove typecast once https://github.com/typescript-eslint/typescript-eslint/pull/3844 is available.
...(getSuggestions(
suggestions,
match.groups.indices?.trim()
) as eslint.TestCaseError<TMessageIds>["suggestions"]),
});
} else {
lines.push(line);
}
});
return {
code: lines.join("\n"),
errors,
};
}