lint-suite 1.6.2 → 1.6.3
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/README.md +149 -2
- package/eslint.cjs +1049 -309
- package/eslint.cjs.map +4 -4
- package/eslint.js +938 -175
- package/eslint.js.map +4 -4
- package/lib/angular-template.d.ts +1 -0
- package/lib/angular-template.d.ts.map +1 -1
- package/lib/angular.d.ts.map +1 -1
- package/lib/base-practices.d.ts.map +1 -1
- package/lib/line-length.const.d.ts +2 -0
- package/lib/line-length.const.d.ts.map +1 -0
- package/lib/rules/common/class-usage.type.d.ts +25 -0
- package/lib/rules/common/class-usage.type.d.ts.map +1 -0
- package/lib/rules/component-metadata.d.ts +5 -0
- package/lib/rules/component-metadata.d.ts.map +1 -0
- package/lib/rules/no-unstyled-classes/common/no-unstyled-classes.type.d.ts +33 -0
- package/lib/rules/no-unstyled-classes/common/no-unstyled-classes.type.d.ts.map +1 -0
- package/lib/rules/no-unstyled-classes/no-unstyled-classes.d.ts +8 -0
- package/lib/rules/no-unstyled-classes/no-unstyled-classes.d.ts.map +1 -0
- package/lib/rules/no-unstyled-classes/styles/component-stylesheets.d.ts +4 -0
- package/lib/rules/no-unstyled-classes/styles/component-stylesheets.d.ts.map +1 -0
- package/lib/rules/no-unstyled-classes/styles/stylesheet-classes.d.ts +3 -0
- package/lib/rules/no-unstyled-classes/styles/stylesheet-classes.d.ts.map +1 -0
- package/lib/rules/no-unstyled-classes/styles/stylesheet-collection.d.ts +4 -0
- package/lib/rules/no-unstyled-classes/styles/stylesheet-collection.d.ts.map +1 -0
- package/lib/rules/no-unstyled-classes/styles/stylesheet-imports.d.ts +2 -0
- package/lib/rules/no-unstyled-classes/styles/stylesheet-imports.d.ts.map +1 -0
- package/lib/rules/no-unstyled-classes/styles/template-stylesheets.d.ts +3 -0
- package/lib/rules/no-unstyled-classes/styles/template-stylesheets.d.ts.map +1 -0
- package/lib/rules/no-unused-angular-instance-fields/rule/angular/angular-metadata-literals.d.ts.map +1 -1
- package/lib/rules/no-unused-classes/common/no-unused-classes.type.d.ts +24 -0
- package/lib/rules/no-unused-classes/common/no-unused-classes.type.d.ts.map +1 -0
- package/lib/rules/no-unused-classes/no-unused-classes.d.ts +8 -0
- package/lib/rules/no-unused-classes/no-unused-classes.d.ts.map +1 -0
- package/lib/rules/no-unused-classes/styles/component-descriptors.d.ts +3 -0
- package/lib/rules/no-unused-classes/styles/component-descriptors.d.ts.map +1 -0
- package/lib/rules/no-unused-classes/styles/stylesheet-components.d.ts +3 -0
- package/lib/rules/no-unused-classes/styles/stylesheet-components.d.ts.map +1 -0
- package/lib/rules/no-unused-classes/template/template-usage.d.ts +3 -0
- package/lib/rules/no-unused-classes/template/template-usage.d.ts.map +1 -0
- package/lib/rules/one-line-guard/one-line-guard.d.ts +10 -0
- package/lib/rules/one-line-guard/one-line-guard.d.ts.map +1 -0
- package/lib/rules/utils/class-expression-literals.util.d.ts +4 -0
- package/lib/rules/utils/class-expression-literals.util.d.ts.map +1 -0
- package/lib/rules/utils/resolved-rules.util.d.ts +5 -0
- package/lib/rules/utils/resolved-rules.util.d.ts.map +1 -0
- package/lib/rules/utils/selector-classes.util.d.ts +7 -0
- package/lib/rules/utils/selector-classes.util.d.ts.map +1 -0
- package/lib/rules/utils/template-classes.util.d.ts +3 -0
- package/lib/rules/utils/template-classes.util.d.ts.map +1 -0
- package/lib/typescript-local-plugin.d.ts.map +1 -1
- package/lib/typescript-safety.d.ts.map +1 -1
- package/package.json +4 -1
- package/prettier.cjs +6 -1
- package/prettier.cjs.map +3 -3
- package/prettier.d.ts.map +1 -1
- package/prettier.js +4 -1
- package/prettier.js.map +3 -3
- package/stylelint.cjs +680 -4
- package/stylelint.cjs.map +4 -4
- package/stylelint.d.ts.map +1 -1
- package/stylelint.js +708 -4
- package/stylelint.js.map +4 -4
package/eslint.js
CHANGED
|
@@ -1,11 +1,677 @@
|
|
|
1
1
|
// packages/lint-suite/src/lib/angular-template.ts
|
|
2
2
|
import { configs } from "angular-eslint";
|
|
3
3
|
import { defineConfig } from "eslint/config";
|
|
4
|
+
|
|
5
|
+
// packages/lint-suite/src/lib/rules/define-plugin.util.ts
|
|
6
|
+
var definePlugin = (name, rules) => {
|
|
7
|
+
const meta7 = { name };
|
|
8
|
+
const plugin = { meta: meta7, rules };
|
|
9
|
+
return plugin;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// packages/lint-suite/src/lib/rules/no-unstyled-classes/no-unstyled-classes.ts
|
|
13
|
+
import { ESLintUtils } from "@typescript-eslint/utils";
|
|
14
|
+
|
|
15
|
+
// packages/lint-suite/src/lib/rules/no-unstyled-classes/styles/component-stylesheets.ts
|
|
16
|
+
import { existsSync } from "node:fs";
|
|
17
|
+
import { dirname, resolve } from "node:path";
|
|
18
|
+
|
|
19
|
+
// packages/lint-suite/src/lib/rules/component-metadata.ts
|
|
20
|
+
import { readFileSync } from "node:fs";
|
|
21
|
+
import {
|
|
22
|
+
ScriptTarget,
|
|
23
|
+
canHaveDecorators,
|
|
24
|
+
createSourceFile,
|
|
25
|
+
forEachChild,
|
|
26
|
+
getDecorators,
|
|
27
|
+
isArrayLiteralExpression,
|
|
28
|
+
isCallExpression,
|
|
29
|
+
isIdentifier,
|
|
30
|
+
isObjectLiteralExpression,
|
|
31
|
+
isPropertyAssignment,
|
|
32
|
+
isStringLiteralLike
|
|
33
|
+
} from "typescript";
|
|
34
|
+
var componentArgument = (decorator) => {
|
|
35
|
+
const { expression } = decorator;
|
|
36
|
+
if (!isCallExpression(expression)) return null;
|
|
37
|
+
if (!isIdentifier(expression.expression)) return null;
|
|
38
|
+
const isComponent = expression.expression.text === "Component";
|
|
39
|
+
if (!isComponent) return null;
|
|
40
|
+
const [argument] = expression.arguments;
|
|
41
|
+
if (argument === void 0) return null;
|
|
42
|
+
if (!isObjectLiteralExpression(argument)) return null;
|
|
43
|
+
return argument;
|
|
44
|
+
};
|
|
45
|
+
var decoratedMetadata = (node) => {
|
|
46
|
+
if (!canHaveDecorators(node)) return null;
|
|
47
|
+
const decorators = getDecorators(node) ?? [];
|
|
48
|
+
for (const decorator of decorators) {
|
|
49
|
+
const metadata = componentArgument(decorator);
|
|
50
|
+
if (metadata !== null) return metadata;
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
};
|
|
54
|
+
var parseComponentMetadata = (text2, path) => {
|
|
55
|
+
const found = [];
|
|
56
|
+
const visit = (node) => {
|
|
57
|
+
const metadata = decoratedMetadata(node);
|
|
58
|
+
if (metadata !== null) found.push(metadata);
|
|
59
|
+
forEachChild(node, visit);
|
|
60
|
+
};
|
|
61
|
+
const source = createSourceFile(path, text2, ScriptTarget.Latest, true);
|
|
62
|
+
forEachChild(source, visit);
|
|
63
|
+
return found;
|
|
64
|
+
};
|
|
65
|
+
var componentMetadata = (path) => {
|
|
66
|
+
try {
|
|
67
|
+
const text2 = readFileSync(path, "utf8");
|
|
68
|
+
return parseComponentMetadata(text2, path);
|
|
69
|
+
} catch {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
var literalText = (node) => {
|
|
74
|
+
if (!isStringLiteralLike(node)) return null;
|
|
75
|
+
return node.text;
|
|
76
|
+
};
|
|
77
|
+
var literalTexts = (node) => {
|
|
78
|
+
const single = literalText(node);
|
|
79
|
+
if (single !== null) return [single];
|
|
80
|
+
if (!isArrayLiteralExpression(node)) return [];
|
|
81
|
+
const texts = [];
|
|
82
|
+
for (const element of node.elements) {
|
|
83
|
+
const text2 = literalText(element);
|
|
84
|
+
if (text2 !== null) texts.push(text2);
|
|
85
|
+
}
|
|
86
|
+
return texts;
|
|
87
|
+
};
|
|
88
|
+
var metadataValue = (metadata, name) => {
|
|
89
|
+
for (const property of metadata.properties) {
|
|
90
|
+
if (!isPropertyAssignment(property)) continue;
|
|
91
|
+
if (!isIdentifier(property.name)) continue;
|
|
92
|
+
const isMatch = property.name.text === name;
|
|
93
|
+
if (isMatch) return property.initializer;
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
};
|
|
97
|
+
var metadataTexts = (metadata, name) => {
|
|
98
|
+
const value = metadataValue(metadata, name);
|
|
99
|
+
if (value === null) return [];
|
|
100
|
+
return literalTexts(value);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// packages/lint-suite/src/lib/rules/no-unstyled-classes/styles/component-stylesheets.ts
|
|
104
|
+
var SIBLING_EXTENSIONS = [".scss", ".css"];
|
|
105
|
+
var HTML_EXTENSION = /\.html$/iu;
|
|
106
|
+
var matchesTemplate = (metadata, directory, templateFilename) => {
|
|
107
|
+
const urls = metadataTexts(metadata, "templateUrl");
|
|
108
|
+
const [templateUrl] = urls;
|
|
109
|
+
if (templateUrl === void 0) return false;
|
|
110
|
+
const declared = resolve(directory, templateUrl);
|
|
111
|
+
const linted = resolve(templateFilename);
|
|
112
|
+
return declared === linted;
|
|
113
|
+
};
|
|
114
|
+
var templateMetadata = (componentPath, templateFilename) => {
|
|
115
|
+
const components = componentMetadata(componentPath);
|
|
116
|
+
const directory = dirname(componentPath);
|
|
117
|
+
const matches = (metadata) => {
|
|
118
|
+
return matchesTemplate(metadata, directory, templateFilename);
|
|
119
|
+
};
|
|
120
|
+
const matched = components.find(matches);
|
|
121
|
+
if (matched !== void 0) return matched;
|
|
122
|
+
const isOnly = components.length === 1;
|
|
123
|
+
if (!isOnly) return null;
|
|
124
|
+
const [only] = components;
|
|
125
|
+
return only ?? null;
|
|
126
|
+
};
|
|
127
|
+
var stylesheetFiles = (paths, directory) => {
|
|
128
|
+
const sources = [];
|
|
129
|
+
for (const path of paths) {
|
|
130
|
+
const resolved = resolve(directory, path);
|
|
131
|
+
const isPresent = existsSync(resolved);
|
|
132
|
+
if (!isPresent) continue;
|
|
133
|
+
const source = { kind: "file", path: resolved };
|
|
134
|
+
sources.push(source);
|
|
135
|
+
}
|
|
136
|
+
return sources;
|
|
137
|
+
};
|
|
138
|
+
var inlineSources = (styles, componentPath) => {
|
|
139
|
+
const sourceOf = (style) => {
|
|
140
|
+
const source = {
|
|
141
|
+
kind: "inline",
|
|
142
|
+
source: style,
|
|
143
|
+
path: componentPath
|
|
144
|
+
};
|
|
145
|
+
return source;
|
|
146
|
+
};
|
|
147
|
+
return styles.map(sourceOf);
|
|
148
|
+
};
|
|
149
|
+
var metadataSources = (componentPath, templateFilename) => {
|
|
150
|
+
const metadata = templateMetadata(componentPath, templateFilename);
|
|
151
|
+
if (metadata === null) return [];
|
|
152
|
+
const singleUrl = metadataTexts(metadata, "styleUrl");
|
|
153
|
+
const listedUrls = metadataTexts(metadata, "styleUrls");
|
|
154
|
+
const styles = metadataTexts(metadata, "styles");
|
|
155
|
+
const directory = dirname(componentPath);
|
|
156
|
+
const urls = [...singleUrl, ...listedUrls];
|
|
157
|
+
const files = stylesheetFiles(urls, directory);
|
|
158
|
+
const inline = inlineSources(styles, componentPath);
|
|
159
|
+
return [...files, ...inline];
|
|
160
|
+
};
|
|
161
|
+
var siblingSources = (templateFilename) => {
|
|
162
|
+
const base2 = templateFilename.replace(HTML_EXTENSION, "");
|
|
163
|
+
const candidateOf = (extension) => `${base2}${extension}`;
|
|
164
|
+
const candidates = SIBLING_EXTENSIONS.map(candidateOf);
|
|
165
|
+
return stylesheetFiles(candidates, dirname(templateFilename));
|
|
166
|
+
};
|
|
167
|
+
var componentStylesheets = (templateFilename) => {
|
|
168
|
+
const componentPath = templateFilename.replace(HTML_EXTENSION, ".ts");
|
|
169
|
+
const sources = metadataSources(componentPath, templateFilename);
|
|
170
|
+
if (sources.length > 0) return sources;
|
|
171
|
+
return siblingSources(templateFilename);
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// packages/lint-suite/src/lib/rules/no-unstyled-classes/styles/stylesheet-classes.ts
|
|
175
|
+
import { readFileSync as readFileSync2, statSync } from "node:fs";
|
|
176
|
+
import { dirname as dirname3 } from "node:path";
|
|
177
|
+
import { parse } from "postcss-scss";
|
|
178
|
+
|
|
179
|
+
// packages/lint-suite/src/lib/rules/no-unstyled-classes/styles/stylesheet-imports.ts
|
|
180
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
181
|
+
import { basename, dirname as dirname2, join, resolve as resolve2 } from "node:path";
|
|
182
|
+
var QUOTED = /'([^']*)'|"([^"]*)"/u;
|
|
183
|
+
var SKIPPED_PREFIXES = ["sass:", "http", "url("];
|
|
184
|
+
var specifierOf = (params) => {
|
|
185
|
+
const match = QUOTED.exec(params);
|
|
186
|
+
if (!match) return null;
|
|
187
|
+
return match[1] ?? match[2] ?? null;
|
|
188
|
+
};
|
|
189
|
+
var isResolvable = (specifier) => {
|
|
190
|
+
const isEmpty = specifier.length === 0;
|
|
191
|
+
if (isEmpty) return false;
|
|
192
|
+
const isSkipped = SKIPPED_PREFIXES.some(
|
|
193
|
+
(prefix) => specifier.startsWith(prefix)
|
|
194
|
+
);
|
|
195
|
+
if (isSkipped) return false;
|
|
196
|
+
return !specifier.endsWith(".css");
|
|
197
|
+
};
|
|
198
|
+
var candidatesOf = (path) => {
|
|
199
|
+
const isStylesheet = path.endsWith(".scss");
|
|
200
|
+
if (isStylesheet) return [path, join(dirname2(path), `_${basename(path)}`)];
|
|
201
|
+
const partial = join(dirname2(path), `_${basename(path)}.scss`);
|
|
202
|
+
return [
|
|
203
|
+
`${path}.scss`,
|
|
204
|
+
partial,
|
|
205
|
+
join(path, "index.scss"),
|
|
206
|
+
join(path, "_index.scss")
|
|
207
|
+
];
|
|
208
|
+
};
|
|
209
|
+
var resolveStylesheetImport = (params, directory) => {
|
|
210
|
+
const specifier = specifierOf(params);
|
|
211
|
+
if (specifier === null) return null;
|
|
212
|
+
const isCandidate = isResolvable(specifier);
|
|
213
|
+
if (!isCandidate) return null;
|
|
214
|
+
const path = resolve2(directory, specifier);
|
|
215
|
+
const candidates = candidatesOf(path);
|
|
216
|
+
const existing = candidates.find((candidate) => existsSync2(candidate));
|
|
217
|
+
return existing ?? null;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
// packages/lint-suite/src/lib/rules/utils/selector-classes.util.ts
|
|
221
|
+
import selectorParser from "postcss-selector-parser";
|
|
222
|
+
var INTERPOLATION_TOKEN = "zzinterpzz";
|
|
223
|
+
var PARENT_TOKEN = "zzparentzz";
|
|
224
|
+
var UNKNOWN_PARENT_SELECTOR = `.${PARENT_TOKEN}`;
|
|
225
|
+
var UNKNOWN_PARTS = new RegExp(
|
|
226
|
+
`${INTERPOLATION_TOKEN}|${PARENT_TOKEN}`,
|
|
227
|
+
"gu"
|
|
228
|
+
);
|
|
229
|
+
var INTERPOLATION = /#\{[^}]*\}/gu;
|
|
230
|
+
var REGEXP_META = /[.*+?^${}()|[\]\\]/gu;
|
|
231
|
+
var escapeRegExp = (part) => {
|
|
232
|
+
return part.replaceAll(REGEXP_META, "\\$&");
|
|
233
|
+
};
|
|
234
|
+
var classNamePattern = (value) => {
|
|
235
|
+
const literals = value.split(UNKNOWN_PARTS).map(escapeRegExp);
|
|
236
|
+
const joined = literals.join(".*");
|
|
237
|
+
return `^${joined}$`;
|
|
238
|
+
};
|
|
239
|
+
var withoutParent = (selector) => {
|
|
240
|
+
return selector.replaceAll("&", UNKNOWN_PARENT_SELECTOR);
|
|
241
|
+
};
|
|
242
|
+
var withParent = (selector, parent) => {
|
|
243
|
+
const hasNesting = selector.includes("&");
|
|
244
|
+
if (hasNesting) return selector.replaceAll("&", parent);
|
|
245
|
+
return `${parent} ${selector}`;
|
|
246
|
+
};
|
|
247
|
+
var resolveSelectors = (selectors, parents) => {
|
|
248
|
+
const hasParents = parents.length > 0;
|
|
249
|
+
if (!hasParents) return selectors.map(withoutParent);
|
|
250
|
+
const resolved = [];
|
|
251
|
+
for (const parent of parents) {
|
|
252
|
+
for (const selector of selectors) {
|
|
253
|
+
resolved.push(withParent(selector, parent));
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return resolved;
|
|
257
|
+
};
|
|
258
|
+
var selectorClasses = (selector) => {
|
|
259
|
+
const exact = [];
|
|
260
|
+
const patterns = [];
|
|
261
|
+
const normalized = selector.replaceAll(INTERPOLATION, INTERPOLATION_TOKEN);
|
|
262
|
+
const collect2 = (node) => {
|
|
263
|
+
const isBareParent = node.value === PARENT_TOKEN;
|
|
264
|
+
if (isBareParent) return;
|
|
265
|
+
const hasInterpolation = node.value.includes(INTERPOLATION_TOKEN);
|
|
266
|
+
const hasUnknownParent = node.value.includes(PARENT_TOKEN);
|
|
267
|
+
const isDynamic = hasInterpolation || hasUnknownParent;
|
|
268
|
+
if (isDynamic) {
|
|
269
|
+
patterns.push(classNamePattern(node.value));
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
exact.push(node.value);
|
|
273
|
+
};
|
|
274
|
+
try {
|
|
275
|
+
const root = selectorParser().astSync(normalized);
|
|
276
|
+
root.walkClasses(collect2);
|
|
277
|
+
} catch {
|
|
278
|
+
const empty = { exact: [], patterns: [] };
|
|
279
|
+
return empty;
|
|
280
|
+
}
|
|
281
|
+
const classes = { exact, patterns };
|
|
282
|
+
return classes;
|
|
283
|
+
};
|
|
284
|
+
var classMatcher = (exact, patterns) => {
|
|
285
|
+
const matches = (name) => {
|
|
286
|
+
const isExact = exact.has(name);
|
|
287
|
+
if (isExact) return true;
|
|
288
|
+
return patterns.some((pattern) => pattern.test(name));
|
|
289
|
+
};
|
|
290
|
+
return matches;
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
// packages/lint-suite/src/lib/rules/utils/resolved-rules.util.ts
|
|
294
|
+
var walkContainer = (container, parents, visit) => {
|
|
295
|
+
for (const node of container.nodes ?? []) {
|
|
296
|
+
if (node.type === "rule") {
|
|
297
|
+
const resolved = resolveSelectors(node.selectors, parents);
|
|
298
|
+
visit(node, resolved, parents);
|
|
299
|
+
walkContainer(node, resolved, visit);
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
if (node.type !== "atrule") continue;
|
|
303
|
+
walkContainer(node, parents, visit);
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
var walkResolvedRules = (root, visit) => {
|
|
307
|
+
walkContainer(root, [], visit);
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
// packages/lint-suite/src/lib/rules/no-unstyled-classes/styles/stylesheet-collection.ts
|
|
311
|
+
var IMPORT_AT_RULES = /* @__PURE__ */ new Set(["use", "import", "forward"]);
|
|
312
|
+
var addSelectors = (selectors, entry) => {
|
|
313
|
+
for (const selector of selectors) {
|
|
314
|
+
const { exact, patterns } = selectorClasses(selector);
|
|
315
|
+
entry.classes.push(...exact);
|
|
316
|
+
entry.patterns.push(...patterns);
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
var addImport = (node, entry, directory) => {
|
|
320
|
+
const isImport = IMPORT_AT_RULES.has(node.name);
|
|
321
|
+
if (!isImport) return;
|
|
322
|
+
const imported = resolveStylesheetImport(node.params, directory);
|
|
323
|
+
if (imported !== null) entry.imports.push(imported);
|
|
324
|
+
};
|
|
325
|
+
var collectStylesheet = (root, directory) => {
|
|
326
|
+
const entry = { classes: [], patterns: [], imports: [] };
|
|
327
|
+
const onRule = (_rule, resolved) => {
|
|
328
|
+
addSelectors(resolved, entry);
|
|
329
|
+
};
|
|
330
|
+
const onAtRule = (node) => {
|
|
331
|
+
addImport(node, entry, directory);
|
|
332
|
+
};
|
|
333
|
+
walkResolvedRules(root, onRule);
|
|
334
|
+
root.walkAtRules(onAtRule);
|
|
335
|
+
return entry;
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
// packages/lint-suite/src/lib/rules/no-unstyled-classes/styles/stylesheet-classes.ts
|
|
339
|
+
var stylesheets = /* @__PURE__ */ new Map();
|
|
340
|
+
var emptyEntry = () => {
|
|
341
|
+
const entry = { classes: [], patterns: [], imports: [] };
|
|
342
|
+
return entry;
|
|
343
|
+
};
|
|
344
|
+
var parseStylesheet = (source, path) => {
|
|
345
|
+
try {
|
|
346
|
+
const root = parse(source, { from: path });
|
|
347
|
+
return collectStylesheet(root, dirname3(path));
|
|
348
|
+
} catch {
|
|
349
|
+
return emptyEntry();
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
var fileEntry = (path) => {
|
|
353
|
+
try {
|
|
354
|
+
const stats = statSync(path, { bigint: true });
|
|
355
|
+
const version = `${stats.mtimeNs}:${stats.size}`;
|
|
356
|
+
const cached = stylesheets.get(path);
|
|
357
|
+
if (cached?.version === version) return cached.entry;
|
|
358
|
+
const entry = parseStylesheet(readFileSync2(path, "utf8"), path);
|
|
359
|
+
const fresh = { entry, version };
|
|
360
|
+
stylesheets.set(path, fresh);
|
|
361
|
+
return entry;
|
|
362
|
+
} catch {
|
|
363
|
+
return emptyEntry();
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
var addEntry = (entry, sink, visited) => {
|
|
367
|
+
for (const name of entry.classes) sink.exact.add(name);
|
|
368
|
+
sink.patterns.push(...entry.patterns);
|
|
369
|
+
for (const imported of entry.imports) {
|
|
370
|
+
const isVisited = visited.has(imported);
|
|
371
|
+
if (isVisited) continue;
|
|
372
|
+
visited.add(imported);
|
|
373
|
+
addEntry(fileEntry(imported), sink, visited);
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
var addSource = (source, sink, visited) => {
|
|
377
|
+
if (source.kind === "file") {
|
|
378
|
+
const isVisited = visited.has(source.path);
|
|
379
|
+
if (isVisited) return;
|
|
380
|
+
visited.add(source.path);
|
|
381
|
+
addEntry(fileEntry(source.path), sink, visited);
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
addEntry(parseStylesheet(source.source, source.path), sink, visited);
|
|
385
|
+
};
|
|
386
|
+
var toRegExp = (pattern) => {
|
|
387
|
+
return new RegExp(pattern, "u");
|
|
388
|
+
};
|
|
389
|
+
var stylesheetClasses = (sources) => {
|
|
390
|
+
const exact = /* @__PURE__ */ new Set();
|
|
391
|
+
const patterns = [];
|
|
392
|
+
const sink = { exact, patterns };
|
|
393
|
+
const visited = /* @__PURE__ */ new Set();
|
|
394
|
+
for (const source of sources) addSource(source, sink, visited);
|
|
395
|
+
const compiled = patterns.map(toRegExp);
|
|
396
|
+
const has = classMatcher(exact, compiled);
|
|
397
|
+
const size = exact.size + compiled.length;
|
|
398
|
+
const classes = { has, size };
|
|
399
|
+
return classes;
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
// packages/lint-suite/src/lib/rules/no-unstyled-classes/styles/template-stylesheets.ts
|
|
403
|
+
var templateStylesheets = (templateFilename, cwd, globalStyles) => {
|
|
404
|
+
let known = null;
|
|
405
|
+
const lookup = () => {
|
|
406
|
+
if (known !== null) return known;
|
|
407
|
+
const component = componentStylesheets(templateFilename);
|
|
408
|
+
const global = stylesheetFiles(globalStyles, cwd);
|
|
409
|
+
const sources = [...component, ...global];
|
|
410
|
+
known = stylesheetClasses(sources);
|
|
411
|
+
return known;
|
|
412
|
+
};
|
|
413
|
+
return lookup;
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
// packages/lint-suite/src/lib/rules/utils/template-classes.util.ts
|
|
417
|
+
import { ParseSourceSpan as ParseSourceSpan2 } from "@angular/compiler";
|
|
418
|
+
|
|
419
|
+
// packages/lint-suite/src/lib/rules/utils/class-expression-literals.util.ts
|
|
420
|
+
import {
|
|
421
|
+
Conditional,
|
|
422
|
+
Interpolation,
|
|
423
|
+
Lexer,
|
|
424
|
+
LiteralArray,
|
|
425
|
+
LiteralMap,
|
|
426
|
+
LiteralPrimitive,
|
|
427
|
+
ParseLocation,
|
|
428
|
+
ParseSourceFile,
|
|
429
|
+
ParseSourceSpan,
|
|
430
|
+
Parser
|
|
431
|
+
} from "@angular/compiler";
|
|
432
|
+
var WHITESPACE = /\s+/u;
|
|
433
|
+
var EXPRESSION_FILE = "class-expression";
|
|
434
|
+
var parser = new Parser(new Lexer());
|
|
435
|
+
var spanOf = (source) => {
|
|
436
|
+
const file = new ParseSourceFile(source, EXPRESSION_FILE);
|
|
437
|
+
const start = new ParseLocation(file, 0, 0, 0);
|
|
438
|
+
const span = new ParseSourceSpan(start, start.moveBy(source.length));
|
|
439
|
+
return span;
|
|
440
|
+
};
|
|
441
|
+
var astOf = (parsed) => {
|
|
442
|
+
const hasErrors = parsed.errors.length > 0;
|
|
443
|
+
if (hasErrors) return null;
|
|
444
|
+
return parsed.ast;
|
|
445
|
+
};
|
|
446
|
+
var parseClassExpression = (source) => {
|
|
447
|
+
try {
|
|
448
|
+
const span = spanOf(source);
|
|
449
|
+
const interpolation = parser.parseInterpolation(source, span, 0, null);
|
|
450
|
+
if (interpolation) return astOf(interpolation);
|
|
451
|
+
const binding = parser.parseBinding(source, span, 0);
|
|
452
|
+
return astOf(binding);
|
|
453
|
+
} catch {
|
|
454
|
+
return null;
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
var addNames = (value, names) => {
|
|
458
|
+
for (const token of value.split(WHITESPACE)) {
|
|
459
|
+
if (token) names.push(token);
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
var addPrimitive = (ast, names) => {
|
|
463
|
+
if (typeof ast.value === "string") addNames(ast.value, names);
|
|
464
|
+
};
|
|
465
|
+
var addMapKeys = (ast, names) => {
|
|
466
|
+
for (const key2 of ast.keys) {
|
|
467
|
+
if (key2.kind !== "spread") addNames(key2.key, names);
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
var addInterpolation = (ast, names) => {
|
|
471
|
+
for (const text2 of ast.strings) addNames(text2, names);
|
|
472
|
+
};
|
|
473
|
+
var collect = (ast, names) => {
|
|
474
|
+
if (ast instanceof LiteralPrimitive) {
|
|
475
|
+
addPrimitive(ast, names);
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
if (ast instanceof LiteralMap) {
|
|
479
|
+
addMapKeys(ast, names);
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
if (ast instanceof Interpolation) {
|
|
483
|
+
addInterpolation(ast, names);
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
if (ast instanceof LiteralArray) {
|
|
487
|
+
for (const expression of ast.expressions) collect(expression, names);
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
if (ast instanceof Conditional) {
|
|
491
|
+
collect(ast.trueExp, names);
|
|
492
|
+
collect(ast.falseExp, names);
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
var classExpressionLiterals = (source) => {
|
|
496
|
+
const ast = parseClassExpression(source);
|
|
497
|
+
if (ast === null) return [];
|
|
498
|
+
const names = [];
|
|
499
|
+
collect(ast, names);
|
|
500
|
+
return [...new Set(names)];
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
// packages/lint-suite/src/lib/rules/utils/template-classes.util.ts
|
|
504
|
+
var CLASS_ATTRIBUTE = "class";
|
|
505
|
+
var CLASS_BINDING_PREFIX = "class.";
|
|
506
|
+
var TOKEN = /\S+/gu;
|
|
507
|
+
var expressionSource = (value) => {
|
|
508
|
+
if (!("source" in value)) return null;
|
|
509
|
+
const { source } = value;
|
|
510
|
+
if (typeof source !== "string") return null;
|
|
511
|
+
return source;
|
|
512
|
+
};
|
|
513
|
+
var staticClasses = (attribute) => {
|
|
514
|
+
const classes = [];
|
|
515
|
+
const valueSpan = attribute.valueSpan ?? attribute.sourceSpan;
|
|
516
|
+
for (const token of attribute.value.matchAll(TOKEN)) {
|
|
517
|
+
const start = valueSpan.start.moveBy(token.index);
|
|
518
|
+
const end = valueSpan.start.moveBy(token.index + token[0].length);
|
|
519
|
+
const span = new ParseSourceSpan2(start, end);
|
|
520
|
+
const templateClass = { name: token[0], span };
|
|
521
|
+
classes.push(templateClass);
|
|
522
|
+
}
|
|
523
|
+
return classes;
|
|
524
|
+
};
|
|
525
|
+
var boundClassName = (input) => {
|
|
526
|
+
const { details } = input.keySpan;
|
|
527
|
+
if (details === null) return null;
|
|
528
|
+
const isClassBinding = details.startsWith(CLASS_BINDING_PREFIX);
|
|
529
|
+
if (!isClassBinding) return null;
|
|
530
|
+
return input.name;
|
|
531
|
+
};
|
|
532
|
+
var isClassExpression = (input) => {
|
|
533
|
+
const isClassName = input.name === CLASS_ATTRIBUTE;
|
|
534
|
+
if (!isClassName) return false;
|
|
535
|
+
const { details } = input.keySpan;
|
|
536
|
+
if (details === null) return true;
|
|
537
|
+
return details === CLASS_ATTRIBUTE;
|
|
538
|
+
};
|
|
539
|
+
var expressionClasses = (input) => {
|
|
540
|
+
const source = expressionSource(input.value);
|
|
541
|
+
if (source === null) return [];
|
|
542
|
+
const names = classExpressionLiterals(source);
|
|
543
|
+
const templateClassOf = (name) => {
|
|
544
|
+
const templateClass = { name, span: input.sourceSpan };
|
|
545
|
+
return templateClass;
|
|
546
|
+
};
|
|
547
|
+
return names.map(templateClassOf);
|
|
548
|
+
};
|
|
549
|
+
var inputClasses = (input) => {
|
|
550
|
+
const bound = boundClassName(input);
|
|
551
|
+
if (bound !== null) {
|
|
552
|
+
const templateClass = { name: bound, span: input.keySpan };
|
|
553
|
+
return [templateClass];
|
|
554
|
+
}
|
|
555
|
+
const isExpression = isClassExpression(input);
|
|
556
|
+
if (!isExpression) return [];
|
|
557
|
+
return expressionClasses(input);
|
|
558
|
+
};
|
|
559
|
+
var templateClasses = (node) => {
|
|
560
|
+
const classes = [];
|
|
561
|
+
for (const attribute of node.attributes) {
|
|
562
|
+
const isClassName = attribute.name === CLASS_ATTRIBUTE;
|
|
563
|
+
if (isClassName) classes.push(...staticClasses(attribute));
|
|
564
|
+
}
|
|
565
|
+
for (const input of node.inputs) {
|
|
566
|
+
classes.push(...inputClasses(input));
|
|
567
|
+
}
|
|
568
|
+
return classes;
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
// packages/lint-suite/src/lib/rules/no-unstyled-classes/no-unstyled-classes.ts
|
|
572
|
+
var PARSER_REQUIRED = "no-unstyled-classes requires '@angular-eslint/template-parser'.";
|
|
573
|
+
var docs = {
|
|
574
|
+
description: "Disallow template class names that no stylesheet of the component selects"
|
|
575
|
+
};
|
|
576
|
+
var messages = {
|
|
577
|
+
unstyledClass: "Class '{{name}}' is not selected by any stylesheet of this template."
|
|
578
|
+
};
|
|
579
|
+
var stringItems = { type: "string" };
|
|
580
|
+
var ignoreClassPatternsSchema = {
|
|
581
|
+
type: "array",
|
|
582
|
+
items: stringItems,
|
|
583
|
+
description: "Regular expressions for class names that are never reported."
|
|
584
|
+
};
|
|
585
|
+
var globalStylesSchema = {
|
|
586
|
+
type: "array",
|
|
587
|
+
items: stringItems,
|
|
588
|
+
description: "Stylesheets merged into the known classes of every template."
|
|
589
|
+
};
|
|
590
|
+
var properties = {
|
|
591
|
+
ignoreClassPatterns: ignoreClassPatternsSchema,
|
|
592
|
+
globalStyles: globalStylesSchema
|
|
593
|
+
};
|
|
594
|
+
var optionsSchema = {
|
|
595
|
+
type: "object",
|
|
596
|
+
properties,
|
|
597
|
+
additionalProperties: false
|
|
598
|
+
};
|
|
599
|
+
var schema = [optionsSchema];
|
|
600
|
+
var meta = {
|
|
601
|
+
type: "problem",
|
|
602
|
+
docs,
|
|
603
|
+
schema,
|
|
604
|
+
messages
|
|
605
|
+
};
|
|
606
|
+
var ruleDefaults = {
|
|
607
|
+
ignoreClassPatterns: ["^(js|qa|mat|cdk|mdc)-"],
|
|
608
|
+
globalStyles: []
|
|
609
|
+
};
|
|
610
|
+
var defaultOptions = [ruleDefaults];
|
|
611
|
+
var createRule = ESLintUtils.RuleCreator(
|
|
612
|
+
() => "https://github.com/F0rty-Tw0/lint-suite#no-unstyled-classes"
|
|
613
|
+
);
|
|
614
|
+
var isTemplateServices = (services) => {
|
|
615
|
+
if (!("convertNodeSourceSpanToLoc" in services)) return false;
|
|
616
|
+
return typeof services.convertNodeSourceSpanToLoc === "function";
|
|
617
|
+
};
|
|
618
|
+
var toRegExp2 = (pattern) => new RegExp(pattern, "u");
|
|
619
|
+
var no_unstyled_classes_default = createRule({
|
|
620
|
+
name: "no-unstyled-classes",
|
|
621
|
+
meta,
|
|
622
|
+
defaultOptions,
|
|
623
|
+
create(context, [options]) {
|
|
624
|
+
const { parserServices } = context.sourceCode;
|
|
625
|
+
if (parserServices === void 0) throw new Error(PARSER_REQUIRED);
|
|
626
|
+
if (!isTemplateServices(parserServices)) throw new Error(PARSER_REQUIRED);
|
|
627
|
+
const ignored = options.ignoreClassPatterns.map(toRegExp2);
|
|
628
|
+
const stylesheets2 = templateStylesheets(
|
|
629
|
+
context.filename,
|
|
630
|
+
context.cwd,
|
|
631
|
+
options.globalStyles
|
|
632
|
+
);
|
|
633
|
+
const listeners = {
|
|
634
|
+
Element(node) {
|
|
635
|
+
const isCustomElement = node.name.includes("-");
|
|
636
|
+
if (isCustomElement) return;
|
|
637
|
+
const classes = templateClasses(node);
|
|
638
|
+
if (classes.length === 0) return;
|
|
639
|
+
const known = stylesheets2();
|
|
640
|
+
if (known.size === 0) return;
|
|
641
|
+
for (const { name, span } of classes) {
|
|
642
|
+
const isIgnored = ignored.some((pattern) => pattern.test(name));
|
|
643
|
+
if (isIgnored) continue;
|
|
644
|
+
const isStyled = known.has(name);
|
|
645
|
+
if (isStyled) continue;
|
|
646
|
+
const loc = parserServices.convertNodeSourceSpanToLoc(span);
|
|
647
|
+
const data = { name };
|
|
648
|
+
const report = {
|
|
649
|
+
loc,
|
|
650
|
+
messageId: "unstyledClass",
|
|
651
|
+
data
|
|
652
|
+
};
|
|
653
|
+
context.report(report);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
};
|
|
657
|
+
return listeners;
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
// packages/lint-suite/src/lib/angular-template.ts
|
|
662
|
+
var lintSuiteAngularTemplatePlugin = definePlugin(
|
|
663
|
+
"lint-suite-angular-template",
|
|
664
|
+
{ "no-unstyled-classes": no_unstyled_classes_default }
|
|
665
|
+
);
|
|
4
666
|
var angularTemplate = defineConfig([
|
|
5
667
|
{
|
|
6
668
|
files: ["**/*.html"],
|
|
7
669
|
extends: [...configs.templateAccessibility, ...configs.templateRecommended],
|
|
670
|
+
plugins: {
|
|
671
|
+
"lint-suite-angular-template": lintSuiteAngularTemplatePlugin
|
|
672
|
+
},
|
|
8
673
|
rules: {
|
|
674
|
+
"lint-suite-angular-template/no-unstyled-classes": "error",
|
|
9
675
|
"@angular-eslint/template/prefer-template-literal": "error",
|
|
10
676
|
"@angular-eslint/template/no-any": "error",
|
|
11
677
|
"@angular-eslint/template/no-duplicate-attributes": "error",
|
|
@@ -77,15 +743,8 @@ import { configs as configs2, processInlineTemplates } from "angular-eslint";
|
|
|
77
743
|
import { defineConfig as defineConfig2 } from "eslint/config";
|
|
78
744
|
import globals from "globals";
|
|
79
745
|
|
|
80
|
-
// packages/lint-suite/src/lib/rules/define-plugin.util.ts
|
|
81
|
-
var definePlugin = (name, rules) => {
|
|
82
|
-
const meta5 = { name };
|
|
83
|
-
const plugin = { meta: meta5, rules };
|
|
84
|
-
return plugin;
|
|
85
|
-
};
|
|
86
|
-
|
|
87
746
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/rule/no-unused-angular-instance-fields.ts
|
|
88
|
-
import { ESLintUtils } from "@typescript-eslint/utils";
|
|
747
|
+
import { ESLintUtils as ESLintUtils2 } from "@typescript-eslint/utils";
|
|
89
748
|
|
|
90
749
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/rule/angular/angular-imports.ts
|
|
91
750
|
import { TSESTree } from "@typescript-eslint/utils";
|
|
@@ -127,8 +786,8 @@ var addAngularImport = (node, imports) => {
|
|
|
127
786
|
imports.set(specifier.local.name, null);
|
|
128
787
|
} else if (specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier && specifier.importKind !== "type") {
|
|
129
788
|
const { imported } = specifier;
|
|
130
|
-
const
|
|
131
|
-
const importedName =
|
|
789
|
+
const isIdentifier9 = imported.type === TSESTree.AST_NODE_TYPES.Identifier;
|
|
790
|
+
const importedName = isIdentifier9 ? imported.name : imported.value;
|
|
132
791
|
imports.set(specifier.local.name, importedName);
|
|
133
792
|
}
|
|
134
793
|
}
|
|
@@ -333,7 +992,7 @@ var methodCandidate = (node, localPrivateOnly, implementedMethods) => {
|
|
|
333
992
|
};
|
|
334
993
|
|
|
335
994
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/rule/angular/angular-metadata-reads.ts
|
|
336
|
-
import { dirname, resolve } from "node:path";
|
|
995
|
+
import { dirname as dirname4, resolve as resolve3 } from "node:path";
|
|
337
996
|
import { TSESTree as TSESTree5 } from "@typescript-eslint/utils";
|
|
338
997
|
|
|
339
998
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/rule/angular/angular-metadata-literals.ts
|
|
@@ -345,7 +1004,9 @@ var text = (node) => {
|
|
|
345
1004
|
if (node?.type !== TSESTree4.AST_NODE_TYPES.TemplateLiteral) return null;
|
|
346
1005
|
const hasExpressions = node.expressions.length > 0;
|
|
347
1006
|
if (hasExpressions) return null;
|
|
348
|
-
|
|
1007
|
+
const [quasi] = node.quasis;
|
|
1008
|
+
if (quasi === void 0) return null;
|
|
1009
|
+
return quasi.value.cooked;
|
|
349
1010
|
};
|
|
350
1011
|
var key = (property) => {
|
|
351
1012
|
if (property.type !== TSESTree4.AST_NODE_TYPES.Property || property.computed) {
|
|
@@ -356,7 +1017,7 @@ var key = (property) => {
|
|
|
356
1017
|
}
|
|
357
1018
|
return text(property.key);
|
|
358
1019
|
};
|
|
359
|
-
var
|
|
1020
|
+
var metadataValue2 = (metadata, name) => {
|
|
360
1021
|
for (const property of metadata.properties) {
|
|
361
1022
|
if (property.type !== TSESTree4.AST_NODE_TYPES.Property) continue;
|
|
362
1023
|
const propertyKey = key(property);
|
|
@@ -367,15 +1028,15 @@ var metadataValue = (metadata, name) => {
|
|
|
367
1028
|
|
|
368
1029
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/rule/angular/angular-template-parsing.ts
|
|
369
1030
|
import {
|
|
370
|
-
Lexer,
|
|
371
|
-
ParseLocation,
|
|
372
|
-
ParseSourceFile,
|
|
373
|
-
ParseSourceSpan,
|
|
374
|
-
Parser,
|
|
1031
|
+
Lexer as Lexer2,
|
|
1032
|
+
ParseLocation as ParseLocation2,
|
|
1033
|
+
ParseSourceFile as ParseSourceFile2,
|
|
1034
|
+
ParseSourceSpan as ParseSourceSpan3,
|
|
1035
|
+
Parser as Parser2,
|
|
375
1036
|
R3TargetBinder,
|
|
376
1037
|
parseTemplate
|
|
377
1038
|
} from "@angular/compiler";
|
|
378
|
-
import { readFileSync, statSync } from "node:fs";
|
|
1039
|
+
import { readFileSync as readFileSync3, statSync as statSync2 } from "node:fs";
|
|
379
1040
|
|
|
380
1041
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/rule/angular/angular-expression-reads.ts
|
|
381
1042
|
import {
|
|
@@ -453,7 +1114,7 @@ var collectAngularExpressionReads = (nodes, boundTarget, action) => {
|
|
|
453
1114
|
|
|
454
1115
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/rule/angular/angular-template-parsing.ts
|
|
455
1116
|
var externalTemplates = /* @__PURE__ */ new Map();
|
|
456
|
-
var
|
|
1117
|
+
var parser2 = new Parser2(new Lexer2());
|
|
457
1118
|
var templateBinder = new R3TargetBinder(null);
|
|
458
1119
|
var templateReads = (template, filename) => {
|
|
459
1120
|
try {
|
|
@@ -470,11 +1131,11 @@ var templateReads = (template, filename) => {
|
|
|
470
1131
|
};
|
|
471
1132
|
var externalTemplateReads = (filename) => {
|
|
472
1133
|
try {
|
|
473
|
-
const stats =
|
|
1134
|
+
const stats = statSync2(filename, { bigint: true });
|
|
474
1135
|
const version = `${stats.mtimeNs}:${stats.size}`;
|
|
475
1136
|
const cached = externalTemplates.get(filename);
|
|
476
1137
|
if (cached?.version === version) return cached.reads;
|
|
477
|
-
const reads = templateReads(
|
|
1138
|
+
const reads = templateReads(readFileSync3(filename, "utf8"), filename);
|
|
478
1139
|
externalTemplates.set(filename, { reads, version });
|
|
479
1140
|
return reads;
|
|
480
1141
|
} catch {
|
|
@@ -482,14 +1143,14 @@ var externalTemplateReads = (filename) => {
|
|
|
482
1143
|
}
|
|
483
1144
|
};
|
|
484
1145
|
var parseExpression = (expression, span, action) => {
|
|
485
|
-
if (action) return
|
|
486
|
-
return
|
|
1146
|
+
if (action) return parser2.parseAction(expression, span, 0);
|
|
1147
|
+
return parser2.parseBinding(expression, span, 0);
|
|
487
1148
|
};
|
|
488
1149
|
var expressionReads = (expression, filename, action) => {
|
|
489
1150
|
try {
|
|
490
|
-
const file = new
|
|
491
|
-
const start = new
|
|
492
|
-
const span = new
|
|
1151
|
+
const file = new ParseSourceFile2(expression, filename);
|
|
1152
|
+
const start = new ParseLocation2(file, 0, 0, 0);
|
|
1153
|
+
const span = new ParseSourceSpan3(start, start.moveBy(expression.length));
|
|
493
1154
|
const result = parseExpression(expression, span, action);
|
|
494
1155
|
if (result.errors.length > 0) return null;
|
|
495
1156
|
return collectAngularExpressionReads([result], void 0, action);
|
|
@@ -542,11 +1203,11 @@ var inlineTemplateReads = (template, reads, filename) => {
|
|
|
542
1203
|
var externalTemplatePropertyReads = (templateUrl, reads, filename) => {
|
|
543
1204
|
if (!templateUrl) return true;
|
|
544
1205
|
const url = text(templateUrl);
|
|
545
|
-
return url !== null && addReads(reads, externalTemplateReads(
|
|
1206
|
+
return url !== null && addReads(reads, externalTemplateReads(resolve3(dirname4(filename), url)));
|
|
546
1207
|
};
|
|
547
1208
|
var componentTemplateReads = (metadata, reads, filename) => {
|
|
548
|
-
const template =
|
|
549
|
-
const templateUrl =
|
|
1209
|
+
const template = metadataValue2(metadata, "template");
|
|
1210
|
+
const templateUrl = metadataValue2(metadata, "templateUrl");
|
|
550
1211
|
return inlineTemplateReads(template, reads, filename) && externalTemplatePropertyReads(templateUrl, reads, filename);
|
|
551
1212
|
};
|
|
552
1213
|
var metadataReads = (options) => {
|
|
@@ -557,7 +1218,7 @@ var metadataReads = (options) => {
|
|
|
557
1218
|
const hasUnreadableKey = metadata.properties.some(isUnreadableKey);
|
|
558
1219
|
if (hasUnreadableKey) return null;
|
|
559
1220
|
const reads = /* @__PURE__ */ new Set();
|
|
560
|
-
const hostValue =
|
|
1221
|
+
const hostValue = metadataValue2(metadata, "host");
|
|
561
1222
|
const hasHostReads = hostReads(hostValue, reads, filename);
|
|
562
1223
|
if (!hasHostReads) return null;
|
|
563
1224
|
if (!options.component) return reads;
|
|
@@ -913,7 +1574,7 @@ var classReadVisitor = (classes, stack, dynamicClasses) => {
|
|
|
913
1574
|
};
|
|
914
1575
|
|
|
915
1576
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/project-usage.ts
|
|
916
|
-
import { isClassElement, isIdentifier as
|
|
1577
|
+
import { isClassElement, isIdentifier as isIdentifier8, isStringLiteralLike as isStringLiteralLike7 } from "typescript";
|
|
917
1578
|
|
|
918
1579
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/angular/angular-directive-index.ts
|
|
919
1580
|
import { CssSelector, SelectorMatcher } from "@angular/compiler";
|
|
@@ -974,8 +1635,8 @@ var buildDirectiveIndex = (classes) => {
|
|
|
974
1635
|
};
|
|
975
1636
|
|
|
976
1637
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/angular/angular-template-reads.ts
|
|
977
|
-
import { readFileSync as
|
|
978
|
-
import { isIdentifier, isStringLiteralLike } from "typescript";
|
|
1638
|
+
import { readFileSync as readFileSync4, statSync as statSync3 } from "node:fs";
|
|
1639
|
+
import { isIdentifier as isIdentifier2, isStringLiteralLike as isStringLiteralLike2 } from "typescript";
|
|
979
1640
|
|
|
980
1641
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/angular/angular-template-read-resolution.ts
|
|
981
1642
|
import {
|
|
@@ -1329,8 +1990,8 @@ var addTemplateReads = ({
|
|
|
1329
1990
|
var memberNameOf = (member) => {
|
|
1330
1991
|
const name = member.name;
|
|
1331
1992
|
if (!name) return [];
|
|
1332
|
-
const isIdentifierName =
|
|
1333
|
-
const isStringName =
|
|
1993
|
+
const isIdentifierName = isIdentifier2(name);
|
|
1994
|
+
const isStringName = isStringLiteralLike2(name);
|
|
1334
1995
|
const isTextName = isIdentifierName || isStringName;
|
|
1335
1996
|
if (!isTextName) return [];
|
|
1336
1997
|
const names = [name.text];
|
|
@@ -1346,13 +2007,13 @@ var unknownTemplateNames = ({ declaration, scope }, allNames) => {
|
|
|
1346
2007
|
return names;
|
|
1347
2008
|
};
|
|
1348
2009
|
var templateFileVersion = (fileName) => {
|
|
1349
|
-
const { mtimeNs, size } =
|
|
2010
|
+
const { mtimeNs, size } = statSync3(fileName, { bigint: true });
|
|
1350
2011
|
const version = { fileName, mtimeNs, size };
|
|
1351
2012
|
return version;
|
|
1352
2013
|
};
|
|
1353
2014
|
var templateFileIsCurrent = (version) => {
|
|
1354
2015
|
try {
|
|
1355
|
-
const current =
|
|
2016
|
+
const current = statSync3(version.fileName, { bigint: true });
|
|
1356
2017
|
return current.mtimeNs === version.mtimeNs && current.size === version.size;
|
|
1357
2018
|
} catch {
|
|
1358
2019
|
return false;
|
|
@@ -1376,7 +2037,7 @@ var templateSourceOf = (angularClass2, allNames, sink, versions) => {
|
|
|
1376
2037
|
const templateFileName = template.fileName;
|
|
1377
2038
|
try {
|
|
1378
2039
|
versions.push(templateFileVersion(templateFileName));
|
|
1379
|
-
const source =
|
|
2040
|
+
const source = readFileSync4(templateFileName, "utf8");
|
|
1380
2041
|
const externalSource = {
|
|
1381
2042
|
fileName: templateFileName,
|
|
1382
2043
|
source
|
|
@@ -1425,7 +2086,7 @@ var collectAngularTemplateReads = ({
|
|
|
1425
2086
|
|
|
1426
2087
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/typescript/typescript-reads.ts
|
|
1427
2088
|
import {
|
|
1428
|
-
forEachChild,
|
|
2089
|
+
forEachChild as forEachChild2,
|
|
1429
2090
|
isClassLike,
|
|
1430
2091
|
isElementAccessExpression,
|
|
1431
2092
|
isPropertyAccessExpression
|
|
@@ -1438,10 +2099,10 @@ import { SyntaxKind, isMethodSignature } from "typescript";
|
|
|
1438
2099
|
import {
|
|
1439
2100
|
SymbolFlags,
|
|
1440
2101
|
isBigIntLiteral,
|
|
1441
|
-
isIdentifier as
|
|
2102
|
+
isIdentifier as isIdentifier3,
|
|
1442
2103
|
isNumericLiteral,
|
|
1443
2104
|
isPrivateIdentifier,
|
|
1444
|
-
isStringLiteralLike as
|
|
2105
|
+
isStringLiteralLike as isStringLiteralLike3
|
|
1445
2106
|
} from "typescript";
|
|
1446
2107
|
var aliasTarget = (checker, symbol) => {
|
|
1447
2108
|
const isAlias = (symbol.flags & SymbolFlags.Alias) !== 0;
|
|
@@ -1496,9 +2157,9 @@ var literalPropertyNames = (type) => {
|
|
|
1496
2157
|
return names;
|
|
1497
2158
|
};
|
|
1498
2159
|
var propertyName2 = (checker, node) => {
|
|
1499
|
-
const isIdentifierName =
|
|
2160
|
+
const isIdentifierName = isIdentifier3(node);
|
|
1500
2161
|
const isPrivateName = isPrivateIdentifier(node);
|
|
1501
|
-
const isStringName =
|
|
2162
|
+
const isStringName = isStringLiteralLike3(node);
|
|
1502
2163
|
const isNumericName = isNumericLiteral(node);
|
|
1503
2164
|
const isBigIntName = isBigIntLiteral(node);
|
|
1504
2165
|
const isLiteralName = isIdentifierName || isPrivateName || isStringName || isNumericName || isBigIntName;
|
|
@@ -1546,31 +2207,31 @@ var collectAngularInterfaceMethods = (node, checker, sink) => {
|
|
|
1546
2207
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/typescript/typescript-destructuring-reads.ts
|
|
1547
2208
|
import {
|
|
1548
2209
|
SyntaxKind as SyntaxKind2,
|
|
1549
|
-
isArrayLiteralExpression as
|
|
2210
|
+
isArrayLiteralExpression as isArrayLiteralExpression3,
|
|
1550
2211
|
isBinaryExpression,
|
|
1551
2212
|
isBindingElement,
|
|
1552
|
-
isObjectLiteralExpression as
|
|
2213
|
+
isObjectLiteralExpression as isObjectLiteralExpression3,
|
|
1553
2214
|
isVariableDeclaration
|
|
1554
2215
|
} from "typescript";
|
|
1555
2216
|
|
|
1556
2217
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/typescript/typescript-assignment-pattern-elements.ts
|
|
1557
2218
|
import {
|
|
1558
|
-
isArrayLiteralExpression,
|
|
1559
|
-
isObjectLiteralExpression,
|
|
2219
|
+
isArrayLiteralExpression as isArrayLiteralExpression2,
|
|
2220
|
+
isObjectLiteralExpression as isObjectLiteralExpression2,
|
|
1560
2221
|
isOmittedExpression,
|
|
1561
|
-
isPropertyAssignment,
|
|
2222
|
+
isPropertyAssignment as isPropertyAssignment2,
|
|
1562
2223
|
isSpreadAssignment,
|
|
1563
2224
|
isSpreadElement
|
|
1564
2225
|
} from "typescript";
|
|
1565
2226
|
var nestedPattern = (expression) => {
|
|
1566
|
-
const isArrayLiteral =
|
|
1567
|
-
const isObjectLiteral =
|
|
2227
|
+
const isArrayLiteral = isArrayLiteralExpression2(expression);
|
|
2228
|
+
const isObjectLiteral = isObjectLiteralExpression2(expression);
|
|
1568
2229
|
const isNested = isArrayLiteral || isObjectLiteral;
|
|
1569
2230
|
if (!isNested) return null;
|
|
1570
2231
|
return expression;
|
|
1571
2232
|
};
|
|
1572
2233
|
var nestedPropertyPattern = (property) => {
|
|
1573
|
-
const isAssignment =
|
|
2234
|
+
const isAssignment = isPropertyAssignment2(property);
|
|
1574
2235
|
if (!isAssignment) return null;
|
|
1575
2236
|
return nestedPattern(property.initializer);
|
|
1576
2237
|
};
|
|
@@ -1609,7 +2270,7 @@ var propertyRead = (property, checker) => {
|
|
|
1609
2270
|
return read;
|
|
1610
2271
|
};
|
|
1611
2272
|
var assignmentPatternElements = (pattern, checker) => {
|
|
1612
|
-
const isArrayPattern =
|
|
2273
|
+
const isArrayPattern = isArrayLiteralExpression2(pattern);
|
|
1613
2274
|
if (isArrayPattern) {
|
|
1614
2275
|
const reads = [];
|
|
1615
2276
|
for (const [index, element] of pattern.elements.entries()) {
|
|
@@ -1626,7 +2287,7 @@ var assignmentPatternElements = (pattern, checker) => {
|
|
|
1626
2287
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/typescript/typescript-binding-pattern-elements.ts
|
|
1627
2288
|
import {
|
|
1628
2289
|
isArrayBindingPattern,
|
|
1629
|
-
isIdentifier as
|
|
2290
|
+
isIdentifier as isIdentifier4,
|
|
1630
2291
|
isObjectBindingPattern,
|
|
1631
2292
|
isOmittedExpression as isOmittedExpression2
|
|
1632
2293
|
} from "typescript";
|
|
@@ -1642,7 +2303,7 @@ var nestedPattern2 = (element) => {
|
|
|
1642
2303
|
};
|
|
1643
2304
|
var bindingNames = (checker, element) => {
|
|
1644
2305
|
if (element.propertyName) return propertyName2(checker, element.propertyName);
|
|
1645
|
-
const isIdentifierName =
|
|
2306
|
+
const isIdentifierName = isIdentifier4(element.name);
|
|
1646
2307
|
if (!isIdentifierName) return null;
|
|
1647
2308
|
return [element.name.text];
|
|
1648
2309
|
};
|
|
@@ -1763,8 +2424,8 @@ var collectAssignmentReads = (node, context) => {
|
|
|
1763
2424
|
if (!isBinary) return;
|
|
1764
2425
|
const isEqualsAssignment = node.operatorToken.kind === SyntaxKind2.EqualsToken;
|
|
1765
2426
|
if (!isEqualsAssignment) return;
|
|
1766
|
-
const isArrayTarget =
|
|
1767
|
-
const isObjectTarget =
|
|
2427
|
+
const isArrayTarget = isArrayLiteralExpression3(node.left);
|
|
2428
|
+
const isObjectTarget = isObjectLiteralExpression3(node.left);
|
|
1768
2429
|
const isDestructuringAssignment = isArrayTarget || isObjectTarget;
|
|
1769
2430
|
if (!isDestructuringAssignment) return;
|
|
1770
2431
|
const rightTypeOf = () => context.checker.getTypeAtLocation(node.right);
|
|
@@ -1780,16 +2441,16 @@ var collectDestructuringReads = (node, checker, sink, candidateNames) => {
|
|
|
1780
2441
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/typescript/typescript-write-targets.ts
|
|
1781
2442
|
import {
|
|
1782
2443
|
SyntaxKind as SyntaxKind3,
|
|
1783
|
-
isArrayLiteralExpression as
|
|
2444
|
+
isArrayLiteralExpression as isArrayLiteralExpression4,
|
|
1784
2445
|
isAsExpression,
|
|
1785
2446
|
isBinaryExpression as isBinaryExpression2,
|
|
1786
2447
|
isDeleteExpression,
|
|
1787
2448
|
isForInStatement,
|
|
1788
2449
|
isForOfStatement,
|
|
1789
2450
|
isNonNullExpression,
|
|
1790
|
-
isObjectLiteralExpression as
|
|
2451
|
+
isObjectLiteralExpression as isObjectLiteralExpression4,
|
|
1791
2452
|
isParenthesizedExpression,
|
|
1792
|
-
isPropertyAssignment as
|
|
2453
|
+
isPropertyAssignment as isPropertyAssignment3,
|
|
1793
2454
|
isSatisfiesExpression,
|
|
1794
2455
|
isSpreadAssignment as isSpreadAssignment2,
|
|
1795
2456
|
isTypeAssertionExpression
|
|
@@ -1806,15 +2467,15 @@ var isExpressionWrapper = (parent, child) => {
|
|
|
1806
2467
|
return parent.expression === child;
|
|
1807
2468
|
};
|
|
1808
2469
|
var isPatternContainer = (parent, child) => {
|
|
1809
|
-
const isArrayLiteral =
|
|
2470
|
+
const isArrayLiteral = isArrayLiteralExpression4(parent);
|
|
1810
2471
|
if (isArrayLiteral) {
|
|
1811
2472
|
return parent.elements.some((element) => element === child);
|
|
1812
2473
|
}
|
|
1813
|
-
const isObjectLiteral =
|
|
2474
|
+
const isObjectLiteral = isObjectLiteralExpression4(parent);
|
|
1814
2475
|
if (isObjectLiteral) {
|
|
1815
2476
|
return parent.properties.some((property) => property === child);
|
|
1816
2477
|
}
|
|
1817
|
-
const isAssignment =
|
|
2478
|
+
const isAssignment = isPropertyAssignment3(parent);
|
|
1818
2479
|
if (isAssignment) return parent.initializer === child;
|
|
1819
2480
|
const isSpread = isSpreadAssignment2(parent);
|
|
1820
2481
|
if (!isSpread) return false;
|
|
@@ -1879,7 +2540,7 @@ var collectTypeScriptReads = (sourceFile, checker, sink, candidateNames) => {
|
|
|
1879
2540
|
collectAngularInterfaceMethods(node, checker, sink);
|
|
1880
2541
|
}
|
|
1881
2542
|
collectDestructuringReads(node, checker, sink, candidateNames);
|
|
1882
|
-
|
|
2543
|
+
forEachChild2(node, visit);
|
|
1883
2544
|
};
|
|
1884
2545
|
visit(sourceFile);
|
|
1885
2546
|
};
|
|
@@ -1987,43 +2648,43 @@ var computeEntry = (index, sourceFile, checker) => {
|
|
|
1987
2648
|
};
|
|
1988
2649
|
const reads = collectFileReads(index, sourceFile, checker, sink);
|
|
1989
2650
|
dependencies.delete(sourceFile);
|
|
1990
|
-
const
|
|
2651
|
+
const fileEntry2 = {
|
|
1991
2652
|
...reads,
|
|
1992
2653
|
declarations,
|
|
1993
2654
|
dependencies,
|
|
1994
2655
|
fallbackNames,
|
|
1995
2656
|
sourceFile
|
|
1996
2657
|
};
|
|
1997
|
-
return
|
|
2658
|
+
return fileEntry2;
|
|
1998
2659
|
};
|
|
1999
2660
|
|
|
2000
2661
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/angular/angular-component-discovery.ts
|
|
2001
2662
|
import {
|
|
2002
|
-
canHaveDecorators as
|
|
2003
|
-
forEachChild as
|
|
2004
|
-
getDecorators as
|
|
2005
|
-
isCallExpression as
|
|
2663
|
+
canHaveDecorators as canHaveDecorators3,
|
|
2664
|
+
forEachChild as forEachChild3,
|
|
2665
|
+
getDecorators as getDecorators3,
|
|
2666
|
+
isCallExpression as isCallExpression3,
|
|
2006
2667
|
isClassLike as isClassLike3,
|
|
2007
|
-
isObjectLiteralExpression as
|
|
2668
|
+
isObjectLiteralExpression as isObjectLiteralExpression5
|
|
2008
2669
|
} from "typescript";
|
|
2009
2670
|
|
|
2010
2671
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/angular/angular-component-scope.ts
|
|
2011
2672
|
import {
|
|
2012
2673
|
SyntaxKind as SyntaxKind4,
|
|
2013
|
-
isArrayLiteralExpression as
|
|
2674
|
+
isArrayLiteralExpression as isArrayLiteralExpression5,
|
|
2014
2675
|
isClassLike as isClassLike2,
|
|
2015
|
-
isIdentifier as
|
|
2676
|
+
isIdentifier as isIdentifier6,
|
|
2016
2677
|
isPropertyAccessExpression as isPropertyAccessExpression3
|
|
2017
2678
|
} from "typescript";
|
|
2018
2679
|
|
|
2019
2680
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/angular/angular-decorator-kind.ts
|
|
2020
2681
|
import {
|
|
2021
2682
|
SymbolFlags as SymbolFlags2,
|
|
2022
|
-
canHaveDecorators,
|
|
2023
|
-
getDecorators,
|
|
2024
|
-
isCallExpression,
|
|
2683
|
+
canHaveDecorators as canHaveDecorators2,
|
|
2684
|
+
getDecorators as getDecorators2,
|
|
2685
|
+
isCallExpression as isCallExpression2,
|
|
2025
2686
|
isImportDeclaration,
|
|
2026
|
-
isStringLiteralLike as
|
|
2687
|
+
isStringLiteralLike as isStringLiteralLike4
|
|
2027
2688
|
} from "typescript";
|
|
2028
2689
|
var decoratorKinds = [
|
|
2029
2690
|
"Component",
|
|
@@ -2045,7 +2706,7 @@ var importedFromAngularCore = (declaration) => {
|
|
|
2045
2706
|
let current = parentOf2(declaration);
|
|
2046
2707
|
while (current) {
|
|
2047
2708
|
if (isImportDeclaration(current)) {
|
|
2048
|
-
return
|
|
2709
|
+
return isStringLiteralLike4(current.moduleSpecifier) && current.moduleSpecifier.text === "@angular/core";
|
|
2049
2710
|
}
|
|
2050
2711
|
current = parentOf2(current);
|
|
2051
2712
|
}
|
|
@@ -2080,10 +2741,10 @@ var angularDecoratorKind = (expression, discovery) => {
|
|
|
2080
2741
|
return name;
|
|
2081
2742
|
};
|
|
2082
2743
|
var classDecoratorKind = (declaration, discovery) => {
|
|
2083
|
-
const hasDecorators =
|
|
2744
|
+
const hasDecorators = canHaveDecorators2(declaration);
|
|
2084
2745
|
if (!hasDecorators) return null;
|
|
2085
|
-
for (const decorator of
|
|
2086
|
-
const isDecoratorCall =
|
|
2746
|
+
for (const decorator of getDecorators2(declaration) ?? []) {
|
|
2747
|
+
const isDecoratorCall = isCallExpression2(decorator.expression);
|
|
2087
2748
|
if (!isDecoratorCall) continue;
|
|
2088
2749
|
const kind = angularDecoratorKind(
|
|
2089
2750
|
decorator.expression.expression,
|
|
@@ -2095,23 +2756,23 @@ var classDecoratorKind = (declaration, discovery) => {
|
|
|
2095
2756
|
};
|
|
2096
2757
|
|
|
2097
2758
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/angular/angular-metadata-values.ts
|
|
2098
|
-
import { dirname as
|
|
2759
|
+
import { dirname as dirname5, resolve as resolve4 } from "node:path";
|
|
2099
2760
|
import {
|
|
2100
|
-
isIdentifier as
|
|
2761
|
+
isIdentifier as isIdentifier5,
|
|
2101
2762
|
isNumericLiteral as isNumericLiteral2,
|
|
2102
2763
|
isPropertyAccessExpression as isPropertyAccessExpression2,
|
|
2103
|
-
isPropertyAssignment as
|
|
2104
|
-
isStringLiteralLike as
|
|
2764
|
+
isPropertyAssignment as isPropertyAssignment4,
|
|
2765
|
+
isStringLiteralLike as isStringLiteralLike5
|
|
2105
2766
|
} from "typescript";
|
|
2106
2767
|
var stringValue = (node, discovery) => {
|
|
2107
2768
|
if (!node) return null;
|
|
2108
|
-
const isStringLiteral =
|
|
2769
|
+
const isStringLiteral = isStringLiteralLike5(node);
|
|
2109
2770
|
if (isStringLiteral) return node.text;
|
|
2110
|
-
const isIdentifierNode =
|
|
2771
|
+
const isIdentifierNode = isIdentifier5(node);
|
|
2111
2772
|
const isPropertyAccessNode = isPropertyAccessExpression2(node);
|
|
2112
2773
|
if (isIdentifierNode || isPropertyAccessNode) {
|
|
2113
2774
|
const symbol = discovery.checker.getSymbolAtLocation(
|
|
2114
|
-
|
|
2775
|
+
isIdentifier5(node) ? node : node.name
|
|
2115
2776
|
);
|
|
2116
2777
|
if (symbol) {
|
|
2117
2778
|
resolveAlias(symbol, discovery);
|
|
@@ -2122,10 +2783,10 @@ var stringValue = (node, discovery) => {
|
|
|
2122
2783
|
};
|
|
2123
2784
|
var metadataProperty = (metadata, name) => {
|
|
2124
2785
|
for (const property of metadata.properties) {
|
|
2125
|
-
const isAssignment =
|
|
2786
|
+
const isAssignment = isPropertyAssignment4(property);
|
|
2126
2787
|
if (!isAssignment) continue;
|
|
2127
|
-
const isIdentifierName =
|
|
2128
|
-
const isStringName =
|
|
2788
|
+
const isIdentifierName = isIdentifier5(property.name);
|
|
2789
|
+
const isStringName = isStringLiteralLike5(property.name);
|
|
2129
2790
|
const isNumericName = isNumericLiteral2(property.name);
|
|
2130
2791
|
const isLiteralName = isIdentifierName || isStringName || isNumericName;
|
|
2131
2792
|
const isPropertyNamed = isLiteralName && property.name.text === name;
|
|
@@ -2145,7 +2806,7 @@ var templateOf = (metadata, fileName, discovery) => {
|
|
|
2145
2806
|
if (url) {
|
|
2146
2807
|
const text2 = stringValue(url, discovery);
|
|
2147
2808
|
if (text2 === null) return void 0;
|
|
2148
|
-
const externalFileName =
|
|
2809
|
+
const externalFileName = resolve4(dirname5(fileName), text2);
|
|
2149
2810
|
const externalTemplate = {
|
|
2150
2811
|
fileName: externalFileName,
|
|
2151
2812
|
kind: "external"
|
|
@@ -2185,7 +2846,7 @@ var scopedClasses = (classes, discovery) => {
|
|
|
2185
2846
|
return scoped;
|
|
2186
2847
|
};
|
|
2187
2848
|
var importedClasses = (element, discovery) => {
|
|
2188
|
-
const isIdentifierElement =
|
|
2849
|
+
const isIdentifierElement = isIdentifier6(element);
|
|
2189
2850
|
const isPropertyAccessElement = isPropertyAccessExpression3(element);
|
|
2190
2851
|
if (!isIdentifierElement && !isPropertyAccessElement) return null;
|
|
2191
2852
|
const target = isIdentifierElement ? element : element.name;
|
|
@@ -2201,7 +2862,7 @@ var scopeOf = (metadata, discovery) => {
|
|
|
2201
2862
|
const isModuleDeclared = standalone === void 0 && !imports;
|
|
2202
2863
|
if (standalone === false || isModuleDeclared) return null;
|
|
2203
2864
|
if (!imports) return [];
|
|
2204
|
-
const isImportsArray =
|
|
2865
|
+
const isImportsArray = isArrayLiteralExpression5(imports);
|
|
2205
2866
|
if (!isImportsArray) return null;
|
|
2206
2867
|
const scope = [];
|
|
2207
2868
|
for (const element of imports.elements) {
|
|
@@ -2254,7 +2915,7 @@ var decoratedClass = (declaration, call, discovery) => {
|
|
|
2254
2915
|
const bareDiscovery = { ...base2, valid: !component };
|
|
2255
2916
|
return bareDiscovery;
|
|
2256
2917
|
}
|
|
2257
|
-
const isMetadataObject =
|
|
2918
|
+
const isMetadataObject = isObjectLiteralExpression5(metadata);
|
|
2258
2919
|
if (!isMetadataObject) {
|
|
2259
2920
|
const invalidDiscovery = { ...base2, valid: false };
|
|
2260
2921
|
return invalidDiscovery;
|
|
@@ -2262,10 +2923,10 @@ var decoratedClass = (declaration, call, discovery) => {
|
|
|
2262
2923
|
return describedClass(base2, metadata, discovery);
|
|
2263
2924
|
};
|
|
2264
2925
|
var angularClass = (declaration, discovery) => {
|
|
2265
|
-
const hasDecorators =
|
|
2926
|
+
const hasDecorators = canHaveDecorators3(declaration);
|
|
2266
2927
|
if (!hasDecorators) return null;
|
|
2267
|
-
for (const decorator of
|
|
2268
|
-
const isDecoratorCall =
|
|
2928
|
+
for (const decorator of getDecorators3(declaration) ?? []) {
|
|
2929
|
+
const isDecoratorCall = isCallExpression3(decorator.expression);
|
|
2269
2930
|
if (!isDecoratorCall) continue;
|
|
2270
2931
|
const found = decoratedClass(declaration, decorator.expression, discovery);
|
|
2271
2932
|
if (found) return found;
|
|
@@ -2283,7 +2944,7 @@ var angularClasses = (sourceFile, checker) => {
|
|
|
2283
2944
|
classes.push(found);
|
|
2284
2945
|
}
|
|
2285
2946
|
}
|
|
2286
|
-
|
|
2947
|
+
forEachChild3(node, visit);
|
|
2287
2948
|
};
|
|
2288
2949
|
visit(sourceFile);
|
|
2289
2950
|
discovery.dependencies.delete(sourceFile);
|
|
@@ -2385,17 +3046,17 @@ var dropStaleTemplateEntries = (index, force) => {
|
|
|
2385
3046
|
|
|
2386
3047
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/project-usage/typescript/typescript-candidate-names.ts
|
|
2387
3048
|
import {
|
|
2388
|
-
canHaveDecorators as
|
|
2389
|
-
forEachChild as
|
|
2390
|
-
getDecorators as
|
|
3049
|
+
canHaveDecorators as canHaveDecorators4,
|
|
3050
|
+
forEachChild as forEachChild4,
|
|
3051
|
+
getDecorators as getDecorators4,
|
|
2391
3052
|
isClassLike as isClassLike4,
|
|
2392
|
-
isIdentifier as
|
|
2393
|
-
isStringLiteralLike as
|
|
3053
|
+
isIdentifier as isIdentifier7,
|
|
3054
|
+
isStringLiteralLike as isStringLiteralLike6
|
|
2394
3055
|
} from "typescript";
|
|
2395
3056
|
var isDecoratedClass = (node) => {
|
|
2396
|
-
const isDecoratable =
|
|
3057
|
+
const isDecoratable = canHaveDecorators4(node);
|
|
2397
3058
|
if (!isDecoratable) return false;
|
|
2398
|
-
const decorators =
|
|
3059
|
+
const decorators = getDecorators4(node);
|
|
2399
3060
|
const decoratorCount = decorators?.length ?? 0;
|
|
2400
3061
|
return decoratorCount > 0;
|
|
2401
3062
|
};
|
|
@@ -2406,8 +3067,8 @@ var addMemberNames = (node, names) => {
|
|
|
2406
3067
|
if (!isDecorated) return;
|
|
2407
3068
|
for (const member of node.members) {
|
|
2408
3069
|
if (!member.name) continue;
|
|
2409
|
-
const isIdentifierName =
|
|
2410
|
-
const isStringName =
|
|
3070
|
+
const isIdentifierName = isIdentifier7(member.name);
|
|
3071
|
+
const isStringName = isStringLiteralLike6(member.name);
|
|
2411
3072
|
const isNamedMember = isIdentifierName || isStringName;
|
|
2412
3073
|
if (isNamedMember) {
|
|
2413
3074
|
names.add(member.name.text);
|
|
@@ -2418,7 +3079,7 @@ var collectCandidateNames = (sourceFile) => {
|
|
|
2418
3079
|
const names = /* @__PURE__ */ new Set();
|
|
2419
3080
|
const visit = (node) => {
|
|
2420
3081
|
addMemberNames(node, names);
|
|
2421
|
-
|
|
3082
|
+
forEachChild4(node, visit);
|
|
2422
3083
|
};
|
|
2423
3084
|
visit(sourceFile);
|
|
2424
3085
|
return names;
|
|
@@ -2537,8 +3198,8 @@ var memberName = (node) => {
|
|
|
2537
3198
|
const isMember = isClassElement(node);
|
|
2538
3199
|
if (!isMember) return null;
|
|
2539
3200
|
if (!node.name) return null;
|
|
2540
|
-
const isIdentifierName =
|
|
2541
|
-
const isStringName =
|
|
3201
|
+
const isIdentifierName = isIdentifier8(node.name);
|
|
3202
|
+
const isStringName = isStringLiteralLike7(node.name);
|
|
2542
3203
|
const isNamedMember = isIdentifierName || isStringName;
|
|
2543
3204
|
if (!isNamedMember) return null;
|
|
2544
3205
|
return node.name.text;
|
|
@@ -2602,10 +3263,10 @@ var projectUsage = (program) => {
|
|
|
2602
3263
|
};
|
|
2603
3264
|
|
|
2604
3265
|
// packages/lint-suite/src/lib/rules/no-unused-angular-instance-fields/rule/no-unused-angular-instance-fields.ts
|
|
2605
|
-
var
|
|
3266
|
+
var docs2 = {
|
|
2606
3267
|
description: "Disallow unread instance fields and methods in Angular components and directives"
|
|
2607
3268
|
};
|
|
2608
|
-
var
|
|
3269
|
+
var messages2 = {
|
|
2609
3270
|
unusedField: "Angular instance field '{{name}}' is never read.",
|
|
2610
3271
|
unusedMethod: "Angular instance method '{{name}}' is never read."
|
|
2611
3272
|
};
|
|
@@ -2618,34 +3279,34 @@ var analysisSchema = {
|
|
|
2618
3279
|
enum: ["local", "project"],
|
|
2619
3280
|
description: "Choose local-file or typed whole-project analysis."
|
|
2620
3281
|
};
|
|
2621
|
-
var
|
|
3282
|
+
var properties2 = {
|
|
2622
3283
|
allowEffectFields: allowEffectFieldsSchema,
|
|
2623
3284
|
analysis: analysisSchema
|
|
2624
3285
|
};
|
|
2625
|
-
var
|
|
3286
|
+
var optionsSchema2 = {
|
|
2626
3287
|
type: "object",
|
|
2627
|
-
properties,
|
|
3288
|
+
properties: properties2,
|
|
2628
3289
|
additionalProperties: false
|
|
2629
3290
|
};
|
|
2630
|
-
var
|
|
2631
|
-
var
|
|
3291
|
+
var schema2 = [optionsSchema2];
|
|
3292
|
+
var meta2 = {
|
|
2632
3293
|
type: "problem",
|
|
2633
|
-
docs,
|
|
2634
|
-
schema,
|
|
2635
|
-
messages
|
|
3294
|
+
docs: docs2,
|
|
3295
|
+
schema: schema2,
|
|
3296
|
+
messages: messages2
|
|
2636
3297
|
};
|
|
2637
|
-
var
|
|
3298
|
+
var ruleDefaults2 = {
|
|
2638
3299
|
allowEffectFields: false,
|
|
2639
3300
|
analysis: "local"
|
|
2640
3301
|
};
|
|
2641
|
-
var
|
|
2642
|
-
var
|
|
3302
|
+
var defaultOptions2 = [ruleDefaults2];
|
|
3303
|
+
var createRule2 = ESLintUtils2.RuleCreator(
|
|
2643
3304
|
() => "https://eslint.org/docs/latest/rules/no-unused-private-class-members"
|
|
2644
3305
|
);
|
|
2645
3306
|
var projectParserServices = (context, analysis) => {
|
|
2646
3307
|
if (analysis !== "project") return void 0;
|
|
2647
3308
|
try {
|
|
2648
|
-
return
|
|
3309
|
+
return ESLintUtils2.getParserServices(context);
|
|
2649
3310
|
} catch {
|
|
2650
3311
|
throw new Error(
|
|
2651
3312
|
"Project analysis requires parser services with type information."
|
|
@@ -2663,10 +3324,10 @@ var projectMemberUsedFor = (parserServices) => {
|
|
|
2663
3324
|
};
|
|
2664
3325
|
return memberUsed;
|
|
2665
3326
|
};
|
|
2666
|
-
var no_unused_angular_instance_fields_default =
|
|
3327
|
+
var no_unused_angular_instance_fields_default = createRule2({
|
|
2667
3328
|
name: "no-unused-instance-fields",
|
|
2668
|
-
meta,
|
|
2669
|
-
defaultOptions,
|
|
3329
|
+
meta: meta2,
|
|
3330
|
+
defaultOptions: defaultOptions2,
|
|
2670
3331
|
create(context, [options]) {
|
|
2671
3332
|
const analysis = options.analysis ?? "local";
|
|
2672
3333
|
const isSpec = isSpecFile(context.filename);
|
|
@@ -2706,6 +3367,9 @@ var no_unused_angular_instance_fields_default = createRule({
|
|
|
2706
3367
|
var lintSuiteAngularPlugin = definePlugin("lint-suite-angular", {
|
|
2707
3368
|
"no-unused-instance-fields": no_unused_angular_instance_fields_default
|
|
2708
3369
|
});
|
|
3370
|
+
var inlineTemplates = processInlineTemplates && {
|
|
3371
|
+
processor: processInlineTemplates
|
|
3372
|
+
};
|
|
2709
3373
|
var angular = defineConfig2([
|
|
2710
3374
|
{
|
|
2711
3375
|
files: ["**/*.ts"],
|
|
@@ -2723,7 +3387,7 @@ var angular = defineConfig2([
|
|
|
2723
3387
|
projectService: true
|
|
2724
3388
|
}
|
|
2725
3389
|
},
|
|
2726
|
-
|
|
3390
|
+
...inlineTemplates,
|
|
2727
3391
|
rules: {
|
|
2728
3392
|
"lint-suite-angular/no-unused-instance-fields": [
|
|
2729
3393
|
"error",
|
|
@@ -2833,6 +3497,11 @@ var baseLimits = defineConfig3([
|
|
|
2833
3497
|
|
|
2834
3498
|
// packages/lint-suite/src/lib/base-practices.ts
|
|
2835
3499
|
import { defineConfig as defineConfig4 } from "eslint/config";
|
|
3500
|
+
|
|
3501
|
+
// packages/lint-suite/src/lib/line-length.const.ts
|
|
3502
|
+
var MAX_LINE_LENGTH = 135;
|
|
3503
|
+
|
|
3504
|
+
// packages/lint-suite/src/lib/base-practices.ts
|
|
2836
3505
|
var basePractices = defineConfig4([
|
|
2837
3506
|
{
|
|
2838
3507
|
files: [
|
|
@@ -2891,7 +3560,7 @@ var basePractices = defineConfig4([
|
|
|
2891
3560
|
"max-len": [
|
|
2892
3561
|
"error",
|
|
2893
3562
|
{
|
|
2894
|
-
code:
|
|
3563
|
+
code: MAX_LINE_LENGTH,
|
|
2895
3564
|
ignoreComments: true
|
|
2896
3565
|
}
|
|
2897
3566
|
],
|
|
@@ -3446,7 +4115,7 @@ var typescriptRecommended = defineConfig17([
|
|
|
3446
4115
|
import { defineConfig as defineConfig18 } from "eslint/config";
|
|
3447
4116
|
|
|
3448
4117
|
// packages/lint-suite/src/lib/rules/explicit-accessibility/explicit-accessibility.ts
|
|
3449
|
-
import { ESLintUtils as
|
|
4118
|
+
import { ESLintUtils as ESLintUtils3, TSESTree as TSESTree10 } from "@typescript-eslint/utils";
|
|
3450
4119
|
|
|
3451
4120
|
// packages/lint-suite/src/lib/rules/explicit-accessibility/common/explicit-accessibility.const.ts
|
|
3452
4121
|
var accessibilities = [
|
|
@@ -3454,10 +4123,10 @@ var accessibilities = [
|
|
|
3454
4123
|
"private",
|
|
3455
4124
|
"protected"
|
|
3456
4125
|
];
|
|
3457
|
-
var
|
|
4126
|
+
var docs3 = {
|
|
3458
4127
|
description: "Require explicit accessibility modifiers on class members"
|
|
3459
4128
|
};
|
|
3460
|
-
var
|
|
4129
|
+
var messages3 = {
|
|
3461
4130
|
missingAccessibility: "Class member '{{ name }}' is missing an explicit accessibility modifier (public/private/protected).",
|
|
3462
4131
|
setAccessibility: "Add the '{{ accessibility }}' modifier."
|
|
3463
4132
|
};
|
|
@@ -3466,27 +4135,27 @@ var defaultAccessibilitySchema = {
|
|
|
3466
4135
|
enum: ["public", "private", "protected", "none"],
|
|
3467
4136
|
description: "The accessibility modifier inserted by the auto-fix; constructors always get public. 'none' reports without an auto-fix and offers all three levels as suggestions."
|
|
3468
4137
|
};
|
|
3469
|
-
var
|
|
4138
|
+
var properties3 = {
|
|
3470
4139
|
defaultAccessibility: defaultAccessibilitySchema
|
|
3471
4140
|
};
|
|
3472
|
-
var
|
|
4141
|
+
var optionsSchema3 = {
|
|
3473
4142
|
type: "object",
|
|
3474
|
-
properties:
|
|
4143
|
+
properties: properties3,
|
|
3475
4144
|
additionalProperties: false
|
|
3476
4145
|
};
|
|
3477
|
-
var
|
|
3478
|
-
var
|
|
4146
|
+
var schema3 = [optionsSchema3];
|
|
4147
|
+
var meta3 = {
|
|
3479
4148
|
type: "suggestion",
|
|
3480
|
-
docs:
|
|
4149
|
+
docs: docs3,
|
|
3481
4150
|
fixable: "code",
|
|
3482
4151
|
hasSuggestions: true,
|
|
3483
|
-
schema:
|
|
3484
|
-
messages:
|
|
4152
|
+
schema: schema3,
|
|
4153
|
+
messages: messages3
|
|
3485
4154
|
};
|
|
3486
|
-
var
|
|
4155
|
+
var defaultOptions3 = [{ defaultAccessibility: "public" }];
|
|
3487
4156
|
|
|
3488
4157
|
// packages/lint-suite/src/lib/rules/explicit-accessibility/explicit-accessibility.ts
|
|
3489
|
-
var
|
|
4158
|
+
var createRule3 = ESLintUtils3.RuleCreator(
|
|
3490
4159
|
() => "https://github.com/F0rty-Tw0/lint-suite#explicit-accessibility"
|
|
3491
4160
|
);
|
|
3492
4161
|
var isPrivateMember = (node) => {
|
|
@@ -3552,10 +4221,10 @@ var suggestionsOf = (node, fixAccessibility, sourceCode) => {
|
|
|
3552
4221
|
};
|
|
3553
4222
|
return accessibilities.filter(isOtherAccessibility).map(suggestionFor);
|
|
3554
4223
|
};
|
|
3555
|
-
var explicit_accessibility_default =
|
|
4224
|
+
var explicit_accessibility_default = createRule3({
|
|
3556
4225
|
name: "explicit-accessibility",
|
|
3557
|
-
meta:
|
|
3558
|
-
defaultOptions:
|
|
4226
|
+
meta: meta3,
|
|
4227
|
+
defaultOptions: defaultOptions3,
|
|
3559
4228
|
create(context, [{ defaultAccessibility = "public" }]) {
|
|
3560
4229
|
const { sourceCode } = context;
|
|
3561
4230
|
const check = (node) => {
|
|
@@ -3592,20 +4261,20 @@ var explicit_accessibility_default = createRule2({
|
|
|
3592
4261
|
});
|
|
3593
4262
|
|
|
3594
4263
|
// packages/lint-suite/src/lib/rules/no-inline-object-types/no-inline-object-types.ts
|
|
3595
|
-
import { ESLintUtils as
|
|
3596
|
-
var
|
|
4264
|
+
import { ESLintUtils as ESLintUtils4, TSESTree as TSESTree11 } from "@typescript-eslint/utils";
|
|
4265
|
+
var docs4 = {
|
|
3597
4266
|
description: "Require nested object types inside a type alias to be extracted to a named type alias"
|
|
3598
4267
|
};
|
|
3599
|
-
var
|
|
4268
|
+
var messages4 = {
|
|
3600
4269
|
inlineObjectType: "Inline object type must be extracted to a named type alias."
|
|
3601
4270
|
};
|
|
3602
|
-
var
|
|
4271
|
+
var meta4 = {
|
|
3603
4272
|
type: "suggestion",
|
|
3604
|
-
docs:
|
|
4273
|
+
docs: docs4,
|
|
3605
4274
|
schema: [],
|
|
3606
|
-
messages:
|
|
4275
|
+
messages: messages4
|
|
3607
4276
|
};
|
|
3608
|
-
var
|
|
4277
|
+
var createRule4 = ESLintUtils4.RuleCreator(
|
|
3609
4278
|
() => "https://github.com/F0rty-Tw0/lint-suite#no-inline-object-types"
|
|
3610
4279
|
);
|
|
3611
4280
|
var enclosingTypeAlias = (node) => {
|
|
@@ -3618,9 +4287,9 @@ var enclosingTypeAlias = (node) => {
|
|
|
3618
4287
|
}
|
|
3619
4288
|
return void 0;
|
|
3620
4289
|
};
|
|
3621
|
-
var no_inline_object_types_default =
|
|
4290
|
+
var no_inline_object_types_default = createRule4({
|
|
3622
4291
|
name: "no-inline-object-types",
|
|
3623
|
-
meta:
|
|
4292
|
+
meta: meta4,
|
|
3624
4293
|
defaultOptions: [],
|
|
3625
4294
|
create(context) {
|
|
3626
4295
|
const listeners = {
|
|
@@ -3640,46 +4309,138 @@ var no_inline_object_types_default = createRule3({
|
|
|
3640
4309
|
}
|
|
3641
4310
|
});
|
|
3642
4311
|
|
|
4312
|
+
// packages/lint-suite/src/lib/rules/one-line-guard/one-line-guard.ts
|
|
4313
|
+
import { ESLintUtils as ESLintUtils5, TSESTree as TSESTree12 } from "@typescript-eslint/utils";
|
|
4314
|
+
var docs5 = {
|
|
4315
|
+
description: "Require a lone return/throw/continue/break guard to drop its braces when the whole if statement fits on one line"
|
|
4316
|
+
};
|
|
4317
|
+
var messages5 = {
|
|
4318
|
+
oneLineGuard: "Lone {{ keyword }} guard fits within {{ max }} columns; write it on one line without braces."
|
|
4319
|
+
};
|
|
4320
|
+
var schema4 = [
|
|
4321
|
+
{
|
|
4322
|
+
type: "object",
|
|
4323
|
+
properties: {
|
|
4324
|
+
maxLineLength: { type: "integer", minimum: 1 }
|
|
4325
|
+
},
|
|
4326
|
+
additionalProperties: false
|
|
4327
|
+
}
|
|
4328
|
+
];
|
|
4329
|
+
var meta5 = {
|
|
4330
|
+
type: "suggestion",
|
|
4331
|
+
docs: docs5,
|
|
4332
|
+
fixable: "code",
|
|
4333
|
+
schema: schema4,
|
|
4334
|
+
messages: messages5
|
|
4335
|
+
};
|
|
4336
|
+
var createRule5 = ESLintUtils5.RuleCreator(
|
|
4337
|
+
() => "https://github.com/F0rty-Tw0/lint-suite#one-line-guard"
|
|
4338
|
+
);
|
|
4339
|
+
var GUARD_KEYWORDS = /* @__PURE__ */ new Set([
|
|
4340
|
+
TSESTree12.AST_NODE_TYPES.ReturnStatement,
|
|
4341
|
+
TSESTree12.AST_NODE_TYPES.ThrowStatement,
|
|
4342
|
+
TSESTree12.AST_NODE_TYPES.ContinueStatement,
|
|
4343
|
+
TSESTree12.AST_NODE_TYPES.BreakStatement
|
|
4344
|
+
]);
|
|
4345
|
+
var soleStatement = (body) => {
|
|
4346
|
+
if (body.type !== TSESTree12.AST_NODE_TYPES.BlockStatement) return void 0;
|
|
4347
|
+
if (body.body.length !== 1) return void 0;
|
|
4348
|
+
return body.body[0];
|
|
4349
|
+
};
|
|
4350
|
+
var guardStatement = (node) => {
|
|
4351
|
+
if (node.alternate) return void 0;
|
|
4352
|
+
const statement = soleStatement(node.consequent);
|
|
4353
|
+
if (!statement) return void 0;
|
|
4354
|
+
const isGuardKeyword = GUARD_KEYWORDS.has(statement.type);
|
|
4355
|
+
if (!isGuardKeyword) return void 0;
|
|
4356
|
+
return statement;
|
|
4357
|
+
};
|
|
4358
|
+
var headText = (node, sourceCode) => {
|
|
4359
|
+
return sourceCode.text.slice(node.range[0], node.consequent.range[0]).trimEnd();
|
|
4360
|
+
};
|
|
4361
|
+
var collapsedLine = (node, head, bodyText, sourceCode) => {
|
|
4362
|
+
const line = sourceCode.lines[node.loc.start.line - 1] ?? "";
|
|
4363
|
+
const prefix = line.slice(0, node.loc.start.column);
|
|
4364
|
+
return `${prefix}${head} ${bodyText}`;
|
|
4365
|
+
};
|
|
4366
|
+
var one_line_guard_default = createRule5({
|
|
4367
|
+
name: "one-line-guard",
|
|
4368
|
+
meta: meta5,
|
|
4369
|
+
defaultOptions: [{ maxLineLength: 80 }],
|
|
4370
|
+
create(context, [{ maxLineLength }]) {
|
|
4371
|
+
const { sourceCode } = context;
|
|
4372
|
+
const listeners = {
|
|
4373
|
+
IfStatement(node) {
|
|
4374
|
+
const statement = guardStatement(node);
|
|
4375
|
+
if (!statement) return;
|
|
4376
|
+
const hasComments = sourceCode.getCommentsInside(node.consequent).length > 0;
|
|
4377
|
+
if (hasComments) return;
|
|
4378
|
+
const head = headText(node, sourceCode);
|
|
4379
|
+
const isMultiLineHead = head.includes("\n");
|
|
4380
|
+
if (isMultiLineHead) return;
|
|
4381
|
+
const bodyText = sourceCode.getText(statement);
|
|
4382
|
+
const isMultiLineBody = bodyText.includes("\n");
|
|
4383
|
+
if (isMultiLineBody) return;
|
|
4384
|
+
const collapsed = collapsedLine(node, head, bodyText, sourceCode);
|
|
4385
|
+
if (collapsed.length > maxLineLength) return;
|
|
4386
|
+
const [keywordToken] = sourceCode.getTokens(statement);
|
|
4387
|
+
if (keywordToken === void 0) return;
|
|
4388
|
+
const keyword = keywordToken.value;
|
|
4389
|
+
const data = { keyword, max: maxLineLength };
|
|
4390
|
+
const fix = (fixer) => fixer.replaceText(node.consequent, bodyText);
|
|
4391
|
+
const report = {
|
|
4392
|
+
node,
|
|
4393
|
+
messageId: "oneLineGuard",
|
|
4394
|
+
data,
|
|
4395
|
+
fix
|
|
4396
|
+
};
|
|
4397
|
+
context.report(report);
|
|
4398
|
+
}
|
|
4399
|
+
};
|
|
4400
|
+
return listeners;
|
|
4401
|
+
}
|
|
4402
|
+
});
|
|
4403
|
+
|
|
3643
4404
|
// packages/lint-suite/src/lib/rules/readonly-type-properties/readonly-type-properties.ts
|
|
3644
|
-
import { ESLintUtils as
|
|
3645
|
-
var
|
|
4405
|
+
import { ESLintUtils as ESLintUtils6, TSESTree as TSESTree13 } from "@typescript-eslint/utils";
|
|
4406
|
+
var docs6 = {
|
|
3646
4407
|
description: "Require readonly on primitive-typed type and interface properties"
|
|
3647
4408
|
};
|
|
3648
|
-
var
|
|
4409
|
+
var messages6 = {
|
|
3649
4410
|
missingReadonly: "Type property '{{ name }}' should be readonly. Disable this rule on the line if mutation is required."
|
|
3650
4411
|
};
|
|
3651
|
-
var
|
|
4412
|
+
var meta6 = {
|
|
3652
4413
|
type: "suggestion",
|
|
3653
|
-
docs:
|
|
4414
|
+
docs: docs6,
|
|
3654
4415
|
fixable: "code",
|
|
3655
4416
|
schema: [],
|
|
3656
|
-
messages:
|
|
4417
|
+
messages: messages6
|
|
3657
4418
|
};
|
|
3658
|
-
var
|
|
4419
|
+
var createRule6 = ESLintUtils6.RuleCreator(
|
|
3659
4420
|
() => "https://github.com/F0rty-Tw0/lint-suite#readonly-type-properties"
|
|
3660
4421
|
);
|
|
3661
4422
|
var propertyName3 = (node, sourceCode) => {
|
|
3662
|
-
if (node.key.type ===
|
|
4423
|
+
if (node.key.type === TSESTree13.AST_NODE_TYPES.Identifier) {
|
|
3663
4424
|
return node.key.name;
|
|
3664
4425
|
}
|
|
3665
4426
|
return sourceCode.getText(node.key);
|
|
3666
4427
|
};
|
|
3667
4428
|
var PRIMITIVE_KEYWORDS = /* @__PURE__ */ new Set([
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
4429
|
+
TSESTree13.AST_NODE_TYPES.TSStringKeyword,
|
|
4430
|
+
TSESTree13.AST_NODE_TYPES.TSNumberKeyword,
|
|
4431
|
+
TSESTree13.AST_NODE_TYPES.TSBooleanKeyword,
|
|
4432
|
+
TSESTree13.AST_NODE_TYPES.TSBigIntKeyword,
|
|
4433
|
+
TSESTree13.AST_NODE_TYPES.TSSymbolKeyword,
|
|
4434
|
+
TSESTree13.AST_NODE_TYPES.TSNullKeyword,
|
|
4435
|
+
TSESTree13.AST_NODE_TYPES.TSUndefinedKeyword
|
|
3675
4436
|
]);
|
|
3676
4437
|
var isPrimitive = (type) => {
|
|
3677
4438
|
const isPrimitiveKeyword = PRIMITIVE_KEYWORDS.has(type.type);
|
|
3678
4439
|
if (isPrimitiveKeyword) return true;
|
|
3679
|
-
if (type.type ===
|
|
4440
|
+
if (type.type === TSESTree13.AST_NODE_TYPES.TSLiteralType || type.type === TSESTree13.AST_NODE_TYPES.TSTemplateLiteralType) {
|
|
3680
4441
|
return true;
|
|
3681
4442
|
}
|
|
3682
|
-
if (type.type ===
|
|
4443
|
+
if (type.type === TSESTree13.AST_NODE_TYPES.TSUnionType || type.type === TSESTree13.AST_NODE_TYPES.TSIntersectionType) {
|
|
3683
4444
|
return type.types.every(isPrimitive);
|
|
3684
4445
|
}
|
|
3685
4446
|
return false;
|
|
@@ -3691,9 +4452,9 @@ var readonlyFix = (node, sourceCode) => {
|
|
|
3691
4452
|
return fixer.insertTextBefore(firstToken, "readonly ");
|
|
3692
4453
|
};
|
|
3693
4454
|
};
|
|
3694
|
-
var readonly_type_properties_default =
|
|
4455
|
+
var readonly_type_properties_default = createRule6({
|
|
3695
4456
|
name: "readonly-type-properties",
|
|
3696
|
-
meta:
|
|
4457
|
+
meta: meta6,
|
|
3697
4458
|
defaultOptions: [],
|
|
3698
4459
|
create(context) {
|
|
3699
4460
|
const { sourceCode } = context;
|
|
@@ -3722,7 +4483,8 @@ var readonly_type_properties_default = createRule4({
|
|
|
3722
4483
|
var localPlugin = definePlugin("local", {
|
|
3723
4484
|
"explicit-accessibility": explicit_accessibility_default,
|
|
3724
4485
|
"readonly-type-properties": readonly_type_properties_default,
|
|
3725
|
-
"no-inline-object-types": no_inline_object_types_default
|
|
4486
|
+
"no-inline-object-types": no_inline_object_types_default,
|
|
4487
|
+
"one-line-guard": one_line_guard_default
|
|
3726
4488
|
});
|
|
3727
4489
|
|
|
3728
4490
|
// packages/lint-suite/src/lib/typescript-safety.ts
|
|
@@ -3734,6 +4496,7 @@ var typescriptSafety = defineConfig18([
|
|
|
3734
4496
|
"local/explicit-accessibility": "error",
|
|
3735
4497
|
"local/readonly-type-properties": "error",
|
|
3736
4498
|
"local/no-inline-object-types": "error",
|
|
4499
|
+
"local/one-line-guard": ["error", { maxLineLength: MAX_LINE_LENGTH }],
|
|
3737
4500
|
"@typescript-eslint/explicit-function-return-type": "error",
|
|
3738
4501
|
"@typescript-eslint/no-empty-function": "error",
|
|
3739
4502
|
"@typescript-eslint/no-unused-vars": "error",
|