eslint-plugin-flawless 0.1.0 → 0.1.1
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 +9 -6
- package/dist/index.d.mts +21 -8
- package/dist/index.mjs +206 -149
- package/package.json +29 -28
package/README.md
CHANGED
|
@@ -171,12 +171,15 @@ pnpm eslint-docs
|
|
|
171
171
|
|
|
172
172
|
<!-- begin auto-generated rules list -->
|
|
173
173
|
|
|
174
|
-
|
|
175
|
-
[
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
|
174
|
+
🔧 Automatically fixable by the
|
|
175
|
+
[`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\
|
|
176
|
+
💭
|
|
177
|
+
Requires [type information](https://typescript-eslint.io/linting/typed-linting).
|
|
178
|
+
|
|
179
|
+
| Name | Description | 🔧 | 💭 |
|
|
180
|
+
| :---------------------------------------------------------------------------------- | :-------------------------------------------------------------- | :-- | :-- |
|
|
181
|
+
| [naming-convention](src/rules/naming-convention/documentation.md) | Enforce naming conventions for everything across a codebase | | 💭 |
|
|
182
|
+
| [yaml-block-key-blank-lines](src/rules/yaml-block-key-blank-lines/documentation.md) | Enforce blank lines around top-level YAML block collection keys | 🔧 | |
|
|
180
183
|
|
|
181
184
|
<!-- end auto-generated rules list -->
|
|
182
185
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { TSESLint } from "@typescript-eslint/utils";
|
|
2
|
-
import "@typescript-eslint/utils/eslint-utils";
|
|
3
|
-
import * as _typescript_eslint_utils_ts_eslint0 from "@typescript-eslint/utils/ts-eslint";
|
|
4
2
|
import { Linter } from "eslint";
|
|
5
3
|
|
|
6
4
|
//#region src/util.d.ts
|
|
@@ -117,8 +115,8 @@ interface NamingSelector {
|
|
|
117
115
|
}
|
|
118
116
|
//#endregion
|
|
119
117
|
//#region src/rules/naming-convention/rule.d.ts
|
|
120
|
-
type MessageIds
|
|
121
|
-
type Options
|
|
118
|
+
type MessageIds = "doesNotMatchFormat" | "doesNotMatchFormatTrimmed" | "missingAffix" | "missingUnderscore" | "satisfyCustom" | "unexpectedUnderscore";
|
|
119
|
+
type Options = Array<NamingSelector>;
|
|
122
120
|
//#endregion
|
|
123
121
|
//#region src/plugin.d.ts
|
|
124
122
|
declare const plugin: {
|
|
@@ -127,7 +125,12 @@ declare const plugin: {
|
|
|
127
125
|
version: string;
|
|
128
126
|
};
|
|
129
127
|
rules: {
|
|
130
|
-
"naming-convention": TSESLint.RuleModule<MessageIds
|
|
128
|
+
"naming-convention": TSESLint.RuleModule<MessageIds, Options, PluginDocumentation, TSESLint.RuleListener> & {
|
|
129
|
+
name: string;
|
|
130
|
+
};
|
|
131
|
+
"yaml-block-key-blank-lines": TSESLint.RuleModule<"blankLine", [], PluginDocumentation, TSESLint.RuleListener> & {
|
|
132
|
+
name: string;
|
|
133
|
+
};
|
|
131
134
|
};
|
|
132
135
|
};
|
|
133
136
|
//#endregion
|
|
@@ -142,7 +145,12 @@ declare const _default: {
|
|
|
142
145
|
version: string;
|
|
143
146
|
};
|
|
144
147
|
rules: {
|
|
145
|
-
"naming-convention":
|
|
148
|
+
"naming-convention": import("${configDir}").RuleModule<MessageIds, Options, PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
149
|
+
name: string;
|
|
150
|
+
};
|
|
151
|
+
"yaml-block-key-blank-lines": import("${configDir}").RuleModule<"blankLine", [], PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
152
|
+
name: string;
|
|
153
|
+
};
|
|
146
154
|
};
|
|
147
155
|
};
|
|
148
156
|
};
|
|
@@ -154,10 +162,15 @@ declare const _default: {
|
|
|
154
162
|
version: string;
|
|
155
163
|
};
|
|
156
164
|
rules: {
|
|
157
|
-
"naming-convention":
|
|
165
|
+
"naming-convention": import("${configDir}").RuleModule<MessageIds, Options, PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
166
|
+
name: string;
|
|
167
|
+
};
|
|
168
|
+
"yaml-block-key-blank-lines": import("${configDir}").RuleModule<"blankLine", [], PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
169
|
+
name: string;
|
|
170
|
+
};
|
|
158
171
|
};
|
|
159
172
|
};
|
|
160
|
-
type RuleOptions = { [K in keyof RuleDefinitions]: RuleDefinitions[K]["defaultOptions"] };
|
|
173
|
+
type RuleOptions = { [K in keyof RuleDefinitions]: NonNullable<RuleDefinitions[K]["defaultOptions"]> };
|
|
161
174
|
type Rules = { [K in keyof RuleOptions]: Linter.RuleEntry<RuleOptions[K]> };
|
|
162
175
|
type RuleDefinitions = typeof plugin.rules;
|
|
163
176
|
//#endregion
|
package/dist/index.mjs
CHANGED
|
@@ -3,21 +3,33 @@ import { requiresQuoting } from "@typescript-eslint/type-utils";
|
|
|
3
3
|
import { ASTUtils, AST_NODE_TYPES, ESLintUtils, TSESLint } from "@typescript-eslint/utils";
|
|
4
4
|
import { RuleCreator, getParserServices } from "@typescript-eslint/utils/eslint-utils";
|
|
5
5
|
import assert from "node:assert";
|
|
6
|
-
|
|
7
6
|
//#region package.json
|
|
8
7
|
var name = "eslint-plugin-flawless";
|
|
9
|
-
var version = "0.1.
|
|
8
|
+
var version = "0.1.1";
|
|
10
9
|
var repository = {
|
|
11
10
|
"url": "git+https://github.com/christopher-buss/eslint-plugin-flawless.git",
|
|
12
11
|
"type": "git"
|
|
13
12
|
};
|
|
14
|
-
|
|
15
13
|
//#endregion
|
|
16
14
|
//#region src/util.ts
|
|
17
|
-
const
|
|
18
|
-
return `${repository.url.replace(/^git\+/, "").replace(/\.git$/, "")}/blob/v${version}/src/rules/${name
|
|
15
|
+
const createRule = RuleCreator((name) => {
|
|
16
|
+
return `${repository.url.replace(/^git\+/, "").replace(/\.git$/, "")}/blob/v${version}/src/rules/${name}/documentation.md`;
|
|
19
17
|
});
|
|
20
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Creates a rule with a docs URL, allowing a rule's `create` to receive a
|
|
20
|
+
* context with a custom `sourceCode` type (such as a YAML source code). The
|
|
21
|
+
* `SourceCode` type parameter defaults to ESLint's `SourceCode`, so standard
|
|
22
|
+
* rules are unaffected.
|
|
23
|
+
*
|
|
24
|
+
* @template Options - The rule's options tuple.
|
|
25
|
+
* @template MessageIds - The rule's message identifiers.
|
|
26
|
+
* @template SourceCode - The source code type exposed on `context.sourceCode`.
|
|
27
|
+
* @param rule - The rule definition (meta, name, defaultOptions, create).
|
|
28
|
+
* @returns The created rule module.
|
|
29
|
+
*/
|
|
30
|
+
function createEslintRule(rule) {
|
|
31
|
+
return createRule(rule);
|
|
32
|
+
}
|
|
21
33
|
//#endregion
|
|
22
34
|
//#region src/utils/is-type-import.ts
|
|
23
35
|
/**
|
|
@@ -34,7 +46,6 @@ const createEslintRule = RuleCreator((name$1) => {
|
|
|
34
46
|
function isTypeImport(definition) {
|
|
35
47
|
return definition?.type === DefinitionType.ImportBinding && (definition.parent.importKind === "type" || definition.node.type === AST_NODE_TYPES.ImportSpecifier && definition.node.importKind === "type");
|
|
36
48
|
}
|
|
37
|
-
|
|
38
49
|
//#endregion
|
|
39
50
|
//#region src/utils/reference-contains-type-query.ts
|
|
40
51
|
/**
|
|
@@ -50,7 +61,6 @@ function referenceContainsTypeQuery(node) {
|
|
|
50
61
|
default: return false;
|
|
51
62
|
}
|
|
52
63
|
}
|
|
53
|
-
|
|
54
64
|
//#endregion
|
|
55
65
|
//#region src/utils/collect-variables.ts
|
|
56
66
|
/**
|
|
@@ -113,10 +123,15 @@ var UnusedVariablesVisitor = class extends Visitor {
|
|
|
113
123
|
}
|
|
114
124
|
TSParameterProperty(node) {
|
|
115
125
|
let identifier;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
126
|
+
switch (node.parameter.type) {
|
|
127
|
+
case AST_NODE_TYPES.AssignmentPattern:
|
|
128
|
+
identifier = node.parameter.left;
|
|
129
|
+
break;
|
|
130
|
+
case AST_NODE_TYPES.Identifier:
|
|
131
|
+
identifier = node.parameter;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
this.markVariableAsUsed(identifier);
|
|
120
135
|
}
|
|
121
136
|
collectUnusedVariables({ scope, variables = {
|
|
122
137
|
unusedVariables: /* @__PURE__ */ new Set(),
|
|
@@ -140,9 +155,9 @@ var UnusedVariablesVisitor = class extends Visitor {
|
|
|
140
155
|
const scope = this.#scopeManager.acquire(node, inner);
|
|
141
156
|
if (scope) {
|
|
142
157
|
if (scope.type === ScopeType.functionExpressionName) {
|
|
143
|
-
const returnValue
|
|
144
|
-
assert(returnValue
|
|
145
|
-
return returnValue
|
|
158
|
+
const returnValue = scope.childScopes[0];
|
|
159
|
+
assert(returnValue, "Function expression name scope should have a child scope");
|
|
160
|
+
return returnValue;
|
|
146
161
|
}
|
|
147
162
|
return scope;
|
|
148
163
|
}
|
|
@@ -157,19 +172,19 @@ var UnusedVariablesVisitor = class extends Visitor {
|
|
|
157
172
|
variableOrIdentifierOrName.eslintUsed = true;
|
|
158
173
|
return;
|
|
159
174
|
}
|
|
160
|
-
let name
|
|
175
|
+
let name;
|
|
161
176
|
let node;
|
|
162
177
|
if (typeof variableOrIdentifierOrName === "string") {
|
|
163
|
-
name
|
|
178
|
+
name = variableOrIdentifierOrName;
|
|
164
179
|
assert(parent, "Parent node is required when marking by name");
|
|
165
180
|
node = parent;
|
|
166
181
|
} else {
|
|
167
|
-
({name
|
|
182
|
+
({name} = variableOrIdentifierOrName);
|
|
168
183
|
node = variableOrIdentifierOrName;
|
|
169
184
|
}
|
|
170
185
|
let currentScope = this.getScope(node);
|
|
171
186
|
while (currentScope) {
|
|
172
|
-
const variable = currentScope.variables.find((scopeVariable) => scopeVariable.name === name
|
|
187
|
+
const variable = currentScope.variables.find((scopeVariable) => scopeVariable.name === name);
|
|
173
188
|
if (variable) {
|
|
174
189
|
variable.eslintUsed = true;
|
|
175
190
|
return;
|
|
@@ -223,8 +238,8 @@ var UnusedVariablesVisitor = class extends Visitor {
|
|
|
223
238
|
if (variable?.defs.length === 0) this.markVariableAsUsed(variable);
|
|
224
239
|
}
|
|
225
240
|
visitFunctionTypeSignature(node) {
|
|
226
|
-
for (const parameter of node.params) this.visitPattern(parameter, (name
|
|
227
|
-
this.markVariableAsUsed(name
|
|
241
|
+
for (const parameter of node.params) this.visitPattern(parameter, (name) => {
|
|
242
|
+
this.markVariableAsUsed(name);
|
|
228
243
|
});
|
|
229
244
|
}
|
|
230
245
|
visitSetter(node) {
|
|
@@ -257,7 +272,7 @@ function isSelfReference(ref, nodes) {
|
|
|
257
272
|
}
|
|
258
273
|
return false;
|
|
259
274
|
}
|
|
260
|
-
const MERGEABLE_TYPES = new Set([
|
|
275
|
+
const MERGEABLE_TYPES = /* @__PURE__ */ new Set([
|
|
261
276
|
AST_NODE_TYPES.ClassDeclaration,
|
|
262
277
|
AST_NODE_TYPES.FunctionDeclaration,
|
|
263
278
|
AST_NODE_TYPES.TSInterfaceDeclaration,
|
|
@@ -289,7 +304,7 @@ function isMergeableExported(variable) {
|
|
|
289
304
|
}
|
|
290
305
|
return false;
|
|
291
306
|
}
|
|
292
|
-
const LOGICAL_ASSIGNMENT_OPERATORS = new Set([
|
|
307
|
+
const LOGICAL_ASSIGNMENT_OPERATORS = /* @__PURE__ */ new Set([
|
|
293
308
|
"&&=",
|
|
294
309
|
"??=",
|
|
295
310
|
"||="
|
|
@@ -409,7 +424,7 @@ function isUsedVariable(variable) {
|
|
|
409
424
|
* @param rhsNode - The RHS node of the previous assignment.
|
|
410
425
|
* @returns The reference is a read to update itself.
|
|
411
426
|
*/
|
|
412
|
-
function isReadForItself(ref, rhsNode
|
|
427
|
+
function isReadForItself(ref, rhsNode) {
|
|
413
428
|
/**
|
|
414
429
|
* Checks whether a given Identifier node exists inside of a function node which can be used later.
|
|
415
430
|
*
|
|
@@ -423,7 +438,7 @@ function isUsedVariable(variable) {
|
|
|
423
438
|
* @param rightHandSideNode - The RHS node of the previous assignment.
|
|
424
439
|
* @returns `true` if the `id` node exists inside of a function node which can be used later.
|
|
425
440
|
*/
|
|
426
|
-
function isInsideOfStorableFunction(id
|
|
441
|
+
function isInsideOfStorableFunction(id, rightHandSideNode) {
|
|
427
442
|
/**
|
|
428
443
|
* Finds a function node from ancestors of a node.
|
|
429
444
|
* @param node - A start node to find.
|
|
@@ -446,32 +461,32 @@ function isUsedVariable(variable) {
|
|
|
446
461
|
* - the funcNode is bound as an argument of a function call.
|
|
447
462
|
* - the function is bound to a property and the object satisfies above conditions.
|
|
448
463
|
*/
|
|
449
|
-
function isStorableFunction(funcNode
|
|
450
|
-
let node = funcNode
|
|
451
|
-
let { parent
|
|
452
|
-
while (parent
|
|
453
|
-
switch (parent
|
|
464
|
+
function isStorableFunction(funcNode, storableRhsNode) {
|
|
465
|
+
let node = funcNode;
|
|
466
|
+
let { parent } = funcNode;
|
|
467
|
+
while (parent && isInside(parent, storableRhsNode)) {
|
|
468
|
+
switch (parent.type) {
|
|
454
469
|
case AST_NODE_TYPES.AssignmentExpression:
|
|
455
470
|
case AST_NODE_TYPES.TaggedTemplateExpression:
|
|
456
471
|
case AST_NODE_TYPES.YieldExpression: return true;
|
|
457
472
|
case AST_NODE_TYPES.CallExpression:
|
|
458
|
-
case AST_NODE_TYPES.NewExpression: return parent
|
|
473
|
+
case AST_NODE_TYPES.NewExpression: return parent.callee !== node;
|
|
459
474
|
case AST_NODE_TYPES.SequenceExpression:
|
|
460
|
-
if (parent
|
|
475
|
+
if (parent.expressions[parent.expressions.length - 1] !== node) return false;
|
|
461
476
|
break;
|
|
462
|
-
default: if (parent
|
|
477
|
+
default: if (parent.type.endsWith("Statement") || parent.type.endsWith("Declaration")) return true;
|
|
463
478
|
}
|
|
464
|
-
node = parent
|
|
465
|
-
({parent
|
|
479
|
+
node = parent;
|
|
480
|
+
({parent} = parent);
|
|
466
481
|
}
|
|
467
482
|
return false;
|
|
468
483
|
}
|
|
469
|
-
const funcNode = getUpperFunction(id
|
|
484
|
+
const funcNode = getUpperFunction(id);
|
|
470
485
|
return !!funcNode && isInside(funcNode, rightHandSideNode) && isStorableFunction(funcNode, rightHandSideNode);
|
|
471
486
|
}
|
|
472
487
|
const id = ref.identifier;
|
|
473
488
|
const { parent } = id;
|
|
474
|
-
return ref.isRead() && (parent.type === AST_NODE_TYPES.AssignmentExpression && !LOGICAL_ASSIGNMENT_OPERATORS.has(parent.operator) && isUnusedExpression(parent) && parent.left === id || parent.type === AST_NODE_TYPES.UpdateExpression && isUnusedExpression(parent) || !!rhsNode
|
|
489
|
+
return ref.isRead() && (parent.type === AST_NODE_TYPES.AssignmentExpression && !LOGICAL_ASSIGNMENT_OPERATORS.has(parent.operator) && isUnusedExpression(parent) && parent.left === id || parent.type === AST_NODE_TYPES.UpdateExpression && isUnusedExpression(parent) || !!rhsNode && isInside(id, rhsNode) && !isInsideOfStorableFunction(id, rhsNode));
|
|
475
490
|
}
|
|
476
491
|
const functionNodes = getFunctionDefinitions(variable);
|
|
477
492
|
const isFunctionDefinition = functionNodes.size > 0;
|
|
@@ -489,7 +504,6 @@ function isUsedVariable(variable) {
|
|
|
489
504
|
return ref.isRead() && !forItself && (isImportedAsType || !referenceContainsTypeQuery(ref.identifier)) && (!isFunctionDefinition || !isSelfReference(ref, functionNodes)) && (!isTypeDecl || !isInsideOneOf(ref, typeDeclNodes)) && (!isModuleDecl || !isSelfReference(ref, moduleDeclNodes)) && (!isEnumDecl || !isSelfReference(ref, enumDeclNodes));
|
|
490
505
|
});
|
|
491
506
|
}
|
|
492
|
-
|
|
493
507
|
//#endregion
|
|
494
508
|
//#region src/rules/naming-convention/utils/enums.ts
|
|
495
509
|
const Selector = {
|
|
@@ -567,7 +581,6 @@ const UnderscoreOption = {
|
|
|
567
581
|
allowDouble: 5,
|
|
568
582
|
allowSingleOrDouble: 6
|
|
569
583
|
};
|
|
570
|
-
|
|
571
584
|
//#endregion
|
|
572
585
|
//#region src/rules/naming-convention/utils/shared.ts
|
|
573
586
|
function isMetaSelector(selector) {
|
|
@@ -580,13 +593,15 @@ function selectorTypeToMessageString(selectorType) {
|
|
|
580
593
|
const notCamelCase = selectorType.replaceAll(/([A-Z])/g, " $1");
|
|
581
594
|
return notCamelCase.charAt(0).toUpperCase() + notCamelCase.slice(1);
|
|
582
595
|
}
|
|
583
|
-
|
|
584
596
|
//#endregion
|
|
585
597
|
//#region src/rules/naming-convention/utils/format.ts
|
|
586
|
-
function
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
598
|
+
function isUppercaseChar(char) {
|
|
599
|
+
return char === char.toUpperCase() && char !== char.toLowerCase();
|
|
600
|
+
}
|
|
601
|
+
function hasStrictCamelHumps(name, isUpper) {
|
|
602
|
+
if (name.startsWith("_")) return false;
|
|
603
|
+
for (let index = 1; index < name.length; ++index) {
|
|
604
|
+
const char = name[index];
|
|
590
605
|
if (char === "_") return false;
|
|
591
606
|
if (isUpper === isUppercaseChar(char)) {
|
|
592
607
|
if (isUpper) return false;
|
|
@@ -594,41 +609,38 @@ function hasStrictCamelHumps(name$1, isUpper) {
|
|
|
594
609
|
}
|
|
595
610
|
return true;
|
|
596
611
|
}
|
|
597
|
-
function isCamelCase(name
|
|
598
|
-
return name
|
|
599
|
-
}
|
|
600
|
-
function isPascalCase(name$1) {
|
|
601
|
-
return name$1.length === 0 || name$1[0] === name$1[0]?.toUpperCase() && !name$1.includes("_");
|
|
602
|
-
}
|
|
603
|
-
function isSnakeCase(name$1) {
|
|
604
|
-
return name$1.length === 0 || name$1 === name$1.toLowerCase() && validateUnderscores(name$1);
|
|
605
|
-
}
|
|
606
|
-
function isStrictCamelCase(name$1) {
|
|
607
|
-
return name$1.length === 0 || name$1[0] === name$1[0]?.toLowerCase() && hasStrictCamelHumps(name$1, false);
|
|
608
|
-
}
|
|
609
|
-
function isStrictPascalCase(name$1) {
|
|
610
|
-
return name$1.length === 0 || name$1[0] === name$1[0]?.toUpperCase() && hasStrictCamelHumps(name$1, true);
|
|
612
|
+
function isCamelCase(name) {
|
|
613
|
+
return name.length === 0 || name[0] === name[0]?.toLowerCase() && !name.includes("_");
|
|
611
614
|
}
|
|
612
|
-
function
|
|
613
|
-
return name
|
|
614
|
-
}
|
|
615
|
-
function isUppercaseChar(char) {
|
|
616
|
-
return char === char.toUpperCase() && char !== char.toLowerCase();
|
|
615
|
+
function isPascalCase(name) {
|
|
616
|
+
return name.length === 0 || name[0] === name[0]?.toUpperCase() && !name.includes("_");
|
|
617
617
|
}
|
|
618
618
|
/**
|
|
619
619
|
* Check for leading trailing and adjacent underscores.
|
|
620
620
|
* @param name - The name to check.
|
|
621
621
|
* @returns True if the underscores are valid.
|
|
622
622
|
*/
|
|
623
|
-
function validateUnderscores(name
|
|
624
|
-
if (name
|
|
623
|
+
function validateUnderscores(name) {
|
|
624
|
+
if (name.startsWith("_")) return false;
|
|
625
625
|
let wasUnderscore = false;
|
|
626
|
-
for (let index = 1; index < name
|
|
626
|
+
for (let index = 1; index < name.length; ++index) if (name[index] === "_") {
|
|
627
627
|
if (wasUnderscore) return false;
|
|
628
628
|
wasUnderscore = true;
|
|
629
629
|
} else wasUnderscore = false;
|
|
630
630
|
return !wasUnderscore;
|
|
631
631
|
}
|
|
632
|
+
function isSnakeCase(name) {
|
|
633
|
+
return name.length === 0 || name === name.toLowerCase() && validateUnderscores(name);
|
|
634
|
+
}
|
|
635
|
+
function isStrictCamelCase(name) {
|
|
636
|
+
return name.length === 0 || name[0] === name[0]?.toLowerCase() && hasStrictCamelHumps(name, false);
|
|
637
|
+
}
|
|
638
|
+
function isStrictPascalCase(name) {
|
|
639
|
+
return name.length === 0 || name[0] === name[0]?.toUpperCase() && hasStrictCamelHumps(name, true);
|
|
640
|
+
}
|
|
641
|
+
function isUpperCase(name) {
|
|
642
|
+
return name.length === 0 || name === name.toUpperCase() && validateUnderscores(name);
|
|
643
|
+
}
|
|
632
644
|
const FormatCheckersMap = {
|
|
633
645
|
[PredefinedFormat.camelCase]: isCamelCase,
|
|
634
646
|
[PredefinedFormat.PascalCase]: isPascalCase,
|
|
@@ -637,12 +649,11 @@ const FormatCheckersMap = {
|
|
|
637
649
|
[PredefinedFormat.StrictPascalCase]: isStrictPascalCase,
|
|
638
650
|
[PredefinedFormat.UPPER_CASE]: isUpperCase
|
|
639
651
|
};
|
|
640
|
-
|
|
641
652
|
//#endregion
|
|
642
653
|
//#region src/rules/naming-convention/utils/validator.ts
|
|
643
654
|
function createValidator(type, context, allConfigs) {
|
|
644
655
|
const selectorType = Selector[type];
|
|
645
|
-
const configs
|
|
656
|
+
const configs = allConfigs.filter((configItem) => {
|
|
646
657
|
return (configItem.selector & selectorType) !== 0 || configItem.selector === MetaSelector.default;
|
|
647
658
|
}).sort((a, b) => {
|
|
648
659
|
if (a.selector === b.selector) return b.modifierWeight - a.modifierWeight;
|
|
@@ -658,53 +669,53 @@ function createValidator(type, context, allConfigs) {
|
|
|
658
669
|
});
|
|
659
670
|
return (node, modifiers = /* @__PURE__ */ new Set()) => {
|
|
660
671
|
const originalName = node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier ? node.name : `${node.value}`;
|
|
661
|
-
for (const config of configs
|
|
672
|
+
for (const config of configs) {
|
|
662
673
|
if (config.filter?.regex.test(originalName) !== config.filter?.match) continue;
|
|
663
674
|
if (config.modifiers?.some((modifier) => !modifiers.has(modifier)) === true) continue;
|
|
664
675
|
if (!isCorrectType(node, config, context, selectorType)) continue;
|
|
665
|
-
let name
|
|
666
|
-
name
|
|
676
|
+
let name = originalName;
|
|
677
|
+
name = validateUnderscore({
|
|
678
|
+
name,
|
|
667
679
|
config,
|
|
668
|
-
name: name$1,
|
|
669
680
|
node,
|
|
670
681
|
originalName,
|
|
671
682
|
position: "leading"
|
|
672
683
|
});
|
|
673
|
-
if (name
|
|
674
|
-
name
|
|
684
|
+
if (name === void 0) return;
|
|
685
|
+
name = validateUnderscore({
|
|
686
|
+
name,
|
|
675
687
|
config,
|
|
676
|
-
name: name$1,
|
|
677
688
|
node,
|
|
678
689
|
originalName,
|
|
679
690
|
position: "trailing"
|
|
680
691
|
});
|
|
681
|
-
if (name
|
|
682
|
-
name
|
|
692
|
+
if (name === void 0) return;
|
|
693
|
+
name = validateAffix({
|
|
694
|
+
name,
|
|
683
695
|
config,
|
|
684
|
-
name: name$1,
|
|
685
696
|
node,
|
|
686
697
|
originalName,
|
|
687
698
|
position: "prefix"
|
|
688
699
|
});
|
|
689
|
-
if (name
|
|
690
|
-
name
|
|
700
|
+
if (name === void 0) return;
|
|
701
|
+
name = validateAffix({
|
|
702
|
+
name,
|
|
691
703
|
config,
|
|
692
|
-
name: name$1,
|
|
693
704
|
node,
|
|
694
705
|
originalName,
|
|
695
706
|
position: "suffix"
|
|
696
707
|
});
|
|
697
|
-
if (name
|
|
708
|
+
if (name === void 0) return;
|
|
698
709
|
if (!validateCustom({
|
|
710
|
+
name,
|
|
699
711
|
config,
|
|
700
|
-
name: name$1,
|
|
701
712
|
node,
|
|
702
713
|
originalName
|
|
703
714
|
})) return;
|
|
704
715
|
if (!validatePredefinedFormat({
|
|
716
|
+
name,
|
|
705
717
|
config,
|
|
706
718
|
modifiers,
|
|
707
|
-
name: name$1,
|
|
708
719
|
node,
|
|
709
720
|
originalName
|
|
710
721
|
})) return;
|
|
@@ -716,10 +727,10 @@ function createValidator(type, context, allConfigs) {
|
|
|
716
727
|
if (custom?.match === true) regexMatch = "match";
|
|
717
728
|
else if (custom?.match === false) regexMatch = "not match";
|
|
718
729
|
return {
|
|
730
|
+
name: originalName,
|
|
719
731
|
affixes: affixes?.join(", "),
|
|
720
732
|
count,
|
|
721
733
|
formats: formats?.map((formatItem) => PredefinedFormatValueToKey[formatItem]).join(", "),
|
|
722
|
-
name: originalName,
|
|
723
734
|
position,
|
|
724
735
|
processedName,
|
|
725
736
|
regex: custom?.regex.toString(),
|
|
@@ -727,24 +738,24 @@ function createValidator(type, context, allConfigs) {
|
|
|
727
738
|
type: selectorTypeToMessageString(type)
|
|
728
739
|
};
|
|
729
740
|
}
|
|
730
|
-
function validateUnderscore({
|
|
741
|
+
function validateUnderscore({ name, config, node, originalName, position }) {
|
|
731
742
|
const option = position === "leading" ? config.leadingUnderscore : config.trailingUnderscore;
|
|
732
|
-
if (!option) return name
|
|
733
|
-
const hasSingleUnderscore = position === "leading" ? () => name
|
|
734
|
-
const trimSingleUnderscore = position === "leading" ? () => name
|
|
735
|
-
const hasDoubleUnderscore = position === "leading" ? () => name
|
|
736
|
-
const trimDoubleUnderscore = position === "leading" ? () => name
|
|
743
|
+
if (!option) return name;
|
|
744
|
+
const hasSingleUnderscore = position === "leading" ? () => name.startsWith("_") : () => name.endsWith("_");
|
|
745
|
+
const trimSingleUnderscore = position === "leading" ? () => name.slice(1) : () => name.slice(0, -1);
|
|
746
|
+
const hasDoubleUnderscore = position === "leading" ? () => name.startsWith("__") : () => name.endsWith("__");
|
|
747
|
+
const trimDoubleUnderscore = position === "leading" ? () => name.slice(2) : () => name.slice(0, -2);
|
|
737
748
|
switch (option) {
|
|
738
749
|
case UnderscoreOption.allow:
|
|
739
750
|
if (hasSingleUnderscore()) return trimSingleUnderscore();
|
|
740
|
-
return name
|
|
751
|
+
return name;
|
|
741
752
|
case UnderscoreOption.allowDouble:
|
|
742
753
|
if (hasDoubleUnderscore()) return trimDoubleUnderscore();
|
|
743
|
-
return name
|
|
754
|
+
return name;
|
|
744
755
|
case UnderscoreOption.allowSingleOrDouble:
|
|
745
756
|
if (hasDoubleUnderscore()) return trimDoubleUnderscore();
|
|
746
757
|
if (hasSingleUnderscore()) return trimSingleUnderscore();
|
|
747
|
-
return name
|
|
758
|
+
return name;
|
|
748
759
|
case UnderscoreOption.forbid:
|
|
749
760
|
if (hasSingleUnderscore()) {
|
|
750
761
|
context.report({
|
|
@@ -758,7 +769,7 @@ function createValidator(type, context, allConfigs) {
|
|
|
758
769
|
});
|
|
759
770
|
return;
|
|
760
771
|
}
|
|
761
|
-
return name
|
|
772
|
+
return name;
|
|
762
773
|
case UnderscoreOption.require:
|
|
763
774
|
if (!hasSingleUnderscore()) {
|
|
764
775
|
context.report({
|
|
@@ -789,12 +800,12 @@ function createValidator(type, context, allConfigs) {
|
|
|
789
800
|
return trimDoubleUnderscore();
|
|
790
801
|
}
|
|
791
802
|
}
|
|
792
|
-
function validateAffix({
|
|
803
|
+
function validateAffix({ name, config, node, originalName, position }) {
|
|
793
804
|
const affixes = config[position];
|
|
794
|
-
if (!affixes || affixes.length === 0) return name
|
|
805
|
+
if (!affixes || affixes.length === 0) return name;
|
|
795
806
|
for (const affix of affixes) {
|
|
796
|
-
const hasAffix = position === "prefix" ? name
|
|
797
|
-
const trimAffix = position === "prefix" ? () => name
|
|
807
|
+
const hasAffix = position === "prefix" ? name.startsWith(affix) : name.endsWith(affix);
|
|
808
|
+
const trimAffix = position === "prefix" ? () => name.slice(affix.length) : () => name.slice(0, -affix.length);
|
|
798
809
|
if (hasAffix) return trimAffix();
|
|
799
810
|
}
|
|
800
811
|
context.report({
|
|
@@ -807,10 +818,10 @@ function createValidator(type, context, allConfigs) {
|
|
|
807
818
|
node
|
|
808
819
|
});
|
|
809
820
|
}
|
|
810
|
-
function validateCustom({
|
|
821
|
+
function validateCustom({ name, config, node, originalName }) {
|
|
811
822
|
const { custom } = config;
|
|
812
823
|
if (!custom) return true;
|
|
813
|
-
const result = custom.regex.test(name
|
|
824
|
+
const result = custom.regex.test(name);
|
|
814
825
|
if (custom.match && result) return true;
|
|
815
826
|
if (!custom.match && !result) return true;
|
|
816
827
|
context.report({
|
|
@@ -823,20 +834,20 @@ function createValidator(type, context, allConfigs) {
|
|
|
823
834
|
});
|
|
824
835
|
return false;
|
|
825
836
|
}
|
|
826
|
-
function validatePredefinedFormat({ config, modifiers,
|
|
837
|
+
function validatePredefinedFormat({ name, config, modifiers, node, originalName }) {
|
|
827
838
|
const formats = config.format;
|
|
828
839
|
if (!formats || formats.length === 0) return true;
|
|
829
840
|
if (!modifiers.has(Modifier.requiresQuotes)) for (const format of formats) {
|
|
830
841
|
const checker = FormatCheckersMap[format];
|
|
831
|
-
if (checker(name
|
|
842
|
+
if (checker(name)) return true;
|
|
832
843
|
}
|
|
833
844
|
context.report({
|
|
834
845
|
data: formatReportData({
|
|
835
846
|
formats,
|
|
836
847
|
originalName,
|
|
837
|
-
processedName: name
|
|
848
|
+
processedName: name
|
|
838
849
|
}),
|
|
839
|
-
messageId: originalName === name
|
|
850
|
+
messageId: originalName === name ? "doesNotMatchFormat" : "doesNotMatchFormatTrimmed",
|
|
840
851
|
node
|
|
841
852
|
});
|
|
842
853
|
return false;
|
|
@@ -859,19 +870,15 @@ function isCorrectType(node, config, context, selector) {
|
|
|
859
870
|
break;
|
|
860
871
|
case TypeModifier.boolean:
|
|
861
872
|
case TypeModifier.number:
|
|
862
|
-
case TypeModifier.string:
|
|
863
|
-
|
|
864
|
-
const allowedTypeString = TypeModifierValueToKey[allowedType];
|
|
865
|
-
if (typeString === allowedTypeString) return true;
|
|
873
|
+
case TypeModifier.string:
|
|
874
|
+
if (checker.typeToString(checker.getWidenedType(checker.getBaseTypeOfLiteralType(type))) === TypeModifierValueToKey[allowedType]) return true;
|
|
866
875
|
break;
|
|
867
|
-
}
|
|
868
876
|
case TypeModifier.function:
|
|
869
877
|
if (isAllTypesMatch(type, (inner) => inner.getCallSignatures().length > 0)) return true;
|
|
870
878
|
break;
|
|
871
879
|
}
|
|
872
880
|
return false;
|
|
873
881
|
}
|
|
874
|
-
|
|
875
882
|
//#endregion
|
|
876
883
|
//#region src/rules/naming-convention/utils/parse-options.ts
|
|
877
884
|
function parseOptions(context) {
|
|
@@ -911,7 +918,6 @@ function normalizeOption(option) {
|
|
|
911
918
|
};
|
|
912
919
|
});
|
|
913
920
|
}
|
|
914
|
-
|
|
915
921
|
//#endregion
|
|
916
922
|
//#region src/rules/naming-convention/utils/schema.ts
|
|
917
923
|
const $DEFS = {
|
|
@@ -1182,11 +1188,10 @@ const SCHEMA = {
|
|
|
1182
1188
|
] },
|
|
1183
1189
|
type: "array"
|
|
1184
1190
|
};
|
|
1185
|
-
|
|
1186
1191
|
//#endregion
|
|
1187
1192
|
//#region src/rules/naming-convention/rule.ts
|
|
1188
|
-
const RULE_NAME = "naming-convention";
|
|
1189
|
-
const messages = {
|
|
1193
|
+
const RULE_NAME$1 = "naming-convention";
|
|
1194
|
+
const messages$1 = {
|
|
1190
1195
|
doesNotMatchFormat: "{{type}} name `{{name}}` must match one of the following formats: {{formats}}",
|
|
1191
1196
|
doesNotMatchFormatTrimmed: "{{type}} name `{{name}}` trimmed as `{{processedName}}` must match one of the following formats: {{formats}}",
|
|
1192
1197
|
missingAffix: "{{type}} name `{{name}}` must have one of the following {{position}}es: {{affixes}}",
|
|
@@ -1216,7 +1221,7 @@ const camelCaseNamingConfig = [
|
|
|
1216
1221
|
selector: "typeLike"
|
|
1217
1222
|
}
|
|
1218
1223
|
];
|
|
1219
|
-
function create(contextWithoutDefaults) {
|
|
1224
|
+
function create$1(contextWithoutDefaults) {
|
|
1220
1225
|
const context = contextWithoutDefaults.options.length > 0 ? contextWithoutDefaults : Object.setPrototypeOf({ options: camelCaseNamingConfig }, contextWithoutDefaults);
|
|
1221
1226
|
const validators = parseOptions(context);
|
|
1222
1227
|
const compilerOptions = getParserServices(context, true).program?.getCompilerOptions() ?? {};
|
|
@@ -1237,11 +1242,11 @@ function create(contextWithoutDefaults) {
|
|
|
1237
1242
|
return modifiers;
|
|
1238
1243
|
}
|
|
1239
1244
|
const { unusedVariables } = collectVariables(context);
|
|
1240
|
-
function isUnused(name
|
|
1245
|
+
function isUnused(name, initialScope) {
|
|
1241
1246
|
let variable = null;
|
|
1242
1247
|
let scope = initialScope;
|
|
1243
1248
|
while (scope) {
|
|
1244
|
-
variable = scope.set.get(name
|
|
1249
|
+
variable = scope.set.get(name) ?? null;
|
|
1245
1250
|
if (variable) break;
|
|
1246
1251
|
scope = scope.upper;
|
|
1247
1252
|
}
|
|
@@ -1323,22 +1328,19 @@ function create(contextWithoutDefaults) {
|
|
|
1323
1328
|
const selectors = {
|
|
1324
1329
|
":matches(PropertyDefinition, TSAbstractPropertyDefinition)[computed = false][value.type != \"ArrowFunctionExpression\"][value.type != \"FunctionExpression\"][value.type != \"TSEmptyBodyFunctionExpression\"]": {
|
|
1325
1330
|
handler: (node, validator) => {
|
|
1326
|
-
|
|
1327
|
-
handleMember(validator, node, modifiers);
|
|
1331
|
+
handleMember(validator, node, getMemberModifiers(node));
|
|
1328
1332
|
},
|
|
1329
1333
|
validator: validators.classProperty
|
|
1330
1334
|
},
|
|
1331
1335
|
":not(ObjectPattern) > Property[computed = false][kind = \"init\"][value.type != \"ArrowFunctionExpression\"][value.type != \"FunctionExpression\"][value.type != \"TSEmptyBodyFunctionExpression\"]": {
|
|
1332
1336
|
handler: (node, validator) => {
|
|
1333
|
-
|
|
1334
|
-
handleMember(validator, node, modifiers);
|
|
1337
|
+
handleMember(validator, node, /* @__PURE__ */ new Set([Modifier.public]));
|
|
1335
1338
|
},
|
|
1336
1339
|
validator: validators.objectLiteralProperty
|
|
1337
1340
|
},
|
|
1338
1341
|
[["TSMethodSignature[computed = false]", "TSPropertySignature[computed = false][typeAnnotation.typeAnnotation.type = \"TSFunctionType\"]"].join(", ")]: {
|
|
1339
1342
|
handler: (node, validator) => {
|
|
1340
|
-
|
|
1341
|
-
handleMember(validator, node, modifiers);
|
|
1343
|
+
handleMember(validator, node, /* @__PURE__ */ new Set([Modifier.public]));
|
|
1342
1344
|
},
|
|
1343
1345
|
validator: validators.typeMethod
|
|
1344
1346
|
},
|
|
@@ -1358,8 +1360,7 @@ function create(contextWithoutDefaults) {
|
|
|
1358
1360
|
},
|
|
1359
1361
|
[["MethodDefinition[computed = false]:matches([kind = \"get\"], [kind = \"set\"])", "TSAbstractMethodDefinition[computed = false]:matches([kind=\"get\"], [kind=\"set\"])"].join(", ")]: {
|
|
1360
1362
|
handler: (node, validator) => {
|
|
1361
|
-
|
|
1362
|
-
handleMember(validator, node, modifiers);
|
|
1363
|
+
handleMember(validator, node, getMemberModifiers(node));
|
|
1363
1364
|
},
|
|
1364
1365
|
validator: validators.classicAccessor
|
|
1365
1366
|
},
|
|
@@ -1369,7 +1370,7 @@ function create(contextWithoutDefaults) {
|
|
|
1369
1370
|
"Property[computed = false][kind = \"init\"][value.type = \"TSEmptyBodyFunctionExpression\"]"
|
|
1370
1371
|
].join(", ")]: {
|
|
1371
1372
|
handler: (node, validator) => {
|
|
1372
|
-
const modifiers = new Set([Modifier.public]);
|
|
1373
|
+
const modifiers = /* @__PURE__ */ new Set([Modifier.public]);
|
|
1373
1374
|
if (isAsyncMemberOrProperty(node)) modifiers.add(Modifier.async);
|
|
1374
1375
|
handleMember(validator, node, modifiers);
|
|
1375
1376
|
},
|
|
@@ -1377,14 +1378,13 @@ function create(contextWithoutDefaults) {
|
|
|
1377
1378
|
},
|
|
1378
1379
|
[[AST_NODE_TYPES.AccessorProperty, AST_NODE_TYPES.TSAbstractAccessorProperty].join(", ")]: {
|
|
1379
1380
|
handler: (node, validator) => {
|
|
1380
|
-
|
|
1381
|
-
handleMember(validator, node, modifiers);
|
|
1381
|
+
handleMember(validator, node, getMemberModifiers(node));
|
|
1382
1382
|
},
|
|
1383
1383
|
validator: validators.autoAccessor
|
|
1384
1384
|
},
|
|
1385
1385
|
"ClassDeclaration, ClassExpression": {
|
|
1386
1386
|
handler: (node, validator) => {
|
|
1387
|
-
const {
|
|
1387
|
+
const { id, abstract } = node;
|
|
1388
1388
|
if (id === null) return;
|
|
1389
1389
|
const modifiers = /* @__PURE__ */ new Set();
|
|
1390
1390
|
const scope = context.sourceCode.getScope(node).upper;
|
|
@@ -1444,8 +1444,7 @@ function create(contextWithoutDefaults) {
|
|
|
1444
1444
|
},
|
|
1445
1445
|
"Property[computed = false]:matches([kind = \"get\"], [kind = \"set\"])": {
|
|
1446
1446
|
handler: (node, validator) => {
|
|
1447
|
-
|
|
1448
|
-
handleMember(validator, node, modifiers);
|
|
1447
|
+
handleMember(validator, node, /* @__PURE__ */ new Set([Modifier.public]));
|
|
1449
1448
|
},
|
|
1450
1449
|
validator: validators.classicAccessor
|
|
1451
1450
|
},
|
|
@@ -1488,7 +1487,7 @@ function create(contextWithoutDefaults) {
|
|
|
1488
1487
|
},
|
|
1489
1488
|
"TSPropertySignature[computed = false][typeAnnotation.typeAnnotation.type != \"TSFunctionType\"]": {
|
|
1490
1489
|
handler: (node, validator) => {
|
|
1491
|
-
const modifiers = new Set([Modifier.public]);
|
|
1490
|
+
const modifiers = /* @__PURE__ */ new Set([Modifier.public]);
|
|
1492
1491
|
if (node.readonly) modifiers.add(Modifier.readonly);
|
|
1493
1492
|
handleMember(validator, node, modifiers);
|
|
1494
1493
|
},
|
|
@@ -1542,7 +1541,8 @@ function create(contextWithoutDefaults) {
|
|
|
1542
1541
|
}));
|
|
1543
1542
|
}
|
|
1544
1543
|
const namingConvention = createEslintRule({
|
|
1545
|
-
|
|
1544
|
+
name: RULE_NAME$1,
|
|
1545
|
+
create: create$1,
|
|
1546
1546
|
defaultOptions: camelCaseNamingConfig,
|
|
1547
1547
|
meta: {
|
|
1548
1548
|
docs: {
|
|
@@ -1552,21 +1552,22 @@ const namingConvention = createEslintRule({
|
|
|
1552
1552
|
},
|
|
1553
1553
|
fixable: void 0,
|
|
1554
1554
|
hasSuggestions: false,
|
|
1555
|
-
messages,
|
|
1555
|
+
messages: messages$1,
|
|
1556
1556
|
schema: SCHEMA,
|
|
1557
1557
|
type: "suggestion"
|
|
1558
|
-
}
|
|
1559
|
-
name: RULE_NAME
|
|
1558
|
+
}
|
|
1560
1559
|
});
|
|
1561
1560
|
function getIdentifiersFromPattern(pattern) {
|
|
1562
1561
|
const identifiers = [];
|
|
1563
|
-
new PatternVisitor({}, pattern, (id) =>
|
|
1562
|
+
new PatternVisitor({}, pattern, (id) => {
|
|
1563
|
+
identifiers.push(id);
|
|
1564
|
+
}).visit(pattern);
|
|
1564
1565
|
return identifiers;
|
|
1565
1566
|
}
|
|
1566
|
-
function isExported(node, name
|
|
1567
|
+
function isExported(node, name, scope) {
|
|
1567
1568
|
if (node?.parent?.type === AST_NODE_TYPES.ExportDefaultDeclaration || node?.parent?.type === AST_NODE_TYPES.ExportNamedDeclaration) return true;
|
|
1568
1569
|
if (scope === null) return false;
|
|
1569
|
-
const variable = scope.set.get(name
|
|
1570
|
+
const variable = scope.set.get(name);
|
|
1570
1571
|
if (variable) for (const ref of variable.references) {
|
|
1571
1572
|
const refParent = ref.identifier.parent;
|
|
1572
1573
|
if (refParent.type === AST_NODE_TYPES.ExportDefaultDeclaration || refParent.type === AST_NODE_TYPES.ExportSpecifier) return true;
|
|
@@ -1578,10 +1579,66 @@ function isGlobal(scope) {
|
|
|
1578
1579
|
return scope.type === TSESLint.Scope.ScopeType.global || scope.type === TSESLint.Scope.ScopeType.module;
|
|
1579
1580
|
}
|
|
1580
1581
|
function requiresQuoting$1(node, target) {
|
|
1581
|
-
|
|
1582
|
-
return requiresQuoting(name$1, target);
|
|
1582
|
+
return requiresQuoting(node.type === AST_NODE_TYPES.Identifier || node.type === AST_NODE_TYPES.PrivateIdentifier ? node.name : `${node.value}`, target);
|
|
1583
1583
|
}
|
|
1584
|
-
|
|
1584
|
+
//#endregion
|
|
1585
|
+
//#region src/rules/yaml-block-key-blank-lines/rule.ts
|
|
1586
|
+
const RULE_NAME = "yaml-block-key-blank-lines";
|
|
1587
|
+
const messages = { blankLine: "Expected {{count}} blank line(s) around this top-level key." };
|
|
1588
|
+
/**
|
|
1589
|
+
* Determines whether a pair value is a block collection (block mapping or block
|
|
1590
|
+
* sequence). Flow collections (`{ ... }` / `[ ... ]`) count as scalars.
|
|
1591
|
+
*
|
|
1592
|
+
* @param value - The value node of a YAML pair.
|
|
1593
|
+
* @returns True if the value is a block mapping or block sequence.
|
|
1594
|
+
*/
|
|
1595
|
+
function isBlock(value) {
|
|
1596
|
+
return value !== null && (value.type === "YAMLMapping" || value.type === "YAMLSequence") && value.style === "block";
|
|
1597
|
+
}
|
|
1598
|
+
function create(context) {
|
|
1599
|
+
const { sourceCode } = context;
|
|
1600
|
+
if (sourceCode.parserServices.isYAML !== true) return {};
|
|
1601
|
+
return { YAMLMapping(yamlNode) {
|
|
1602
|
+
if (yamlNode.parent.type !== "YAMLDocument") return;
|
|
1603
|
+
const { pairs } = yamlNode;
|
|
1604
|
+
for (let index = 1; index < pairs.length; index += 1) {
|
|
1605
|
+
const previous = pairs[index - 1];
|
|
1606
|
+
const current = pairs[index];
|
|
1607
|
+
if (previous === void 0 || current === void 0) continue;
|
|
1608
|
+
const left = sourceCode.getLastToken(previous);
|
|
1609
|
+
const right = sourceCode.getFirstToken(current);
|
|
1610
|
+
if (sourceCode.commentsExistBetween(left, right)) continue;
|
|
1611
|
+
const blanks = right.loc.start.line - left.loc.end.line - 1;
|
|
1612
|
+
const want = isBlock(previous.value) || isBlock(current.value) ? 1 : 0;
|
|
1613
|
+
if (blanks === want) continue;
|
|
1614
|
+
context.report({
|
|
1615
|
+
data: { count: want },
|
|
1616
|
+
fix(fixer) {
|
|
1617
|
+
return fixer.replaceTextRange([left.range[1], right.range[0]], "\n".repeat(want + 1));
|
|
1618
|
+
},
|
|
1619
|
+
loc: (current.key ?? current).loc,
|
|
1620
|
+
messageId: "blankLine"
|
|
1621
|
+
});
|
|
1622
|
+
}
|
|
1623
|
+
} };
|
|
1624
|
+
}
|
|
1625
|
+
const yamlBlockKeyBlankLines = createEslintRule({
|
|
1626
|
+
name: RULE_NAME,
|
|
1627
|
+
create,
|
|
1628
|
+
defaultOptions: [],
|
|
1629
|
+
meta: {
|
|
1630
|
+
docs: {
|
|
1631
|
+
description: "Enforce blank lines around top-level YAML block collection keys",
|
|
1632
|
+
recommended: false,
|
|
1633
|
+
requiresTypeChecking: false
|
|
1634
|
+
},
|
|
1635
|
+
fixable: "whitespace",
|
|
1636
|
+
hasSuggestions: false,
|
|
1637
|
+
messages,
|
|
1638
|
+
schema: [],
|
|
1639
|
+
type: "layout"
|
|
1640
|
+
}
|
|
1641
|
+
});
|
|
1585
1642
|
//#endregion
|
|
1586
1643
|
//#region src/plugin.ts
|
|
1587
1644
|
const PLUGIN_NAME = name.replace(/^eslint-plugin-/, "");
|
|
@@ -1600,23 +1657,23 @@ const plugin = {
|
|
|
1600
1657
|
name: PLUGIN_NAME,
|
|
1601
1658
|
version
|
|
1602
1659
|
},
|
|
1603
|
-
rules: {
|
|
1660
|
+
rules: {
|
|
1661
|
+
"naming-convention": namingConvention,
|
|
1662
|
+
"yaml-block-key-blank-lines": yamlBlockKeyBlankLines
|
|
1663
|
+
}
|
|
1604
1664
|
};
|
|
1605
|
-
|
|
1606
|
-
|
|
1665
|
+
getRules(PLUGIN_NAME, plugin.rules);
|
|
1607
1666
|
//#endregion
|
|
1608
1667
|
//#region src/configs/index.ts
|
|
1609
1668
|
const configs = { recommended: {
|
|
1610
1669
|
plugins: { [PLUGIN_NAME]: plugin },
|
|
1611
1670
|
rules: {}
|
|
1612
1671
|
} };
|
|
1613
|
-
|
|
1614
1672
|
//#endregion
|
|
1615
1673
|
//#region src/index.ts
|
|
1616
1674
|
var src_default = {
|
|
1617
1675
|
...plugin,
|
|
1618
1676
|
configs
|
|
1619
1677
|
};
|
|
1620
|
-
|
|
1621
1678
|
//#endregion
|
|
1622
|
-
export { src_default as default };
|
|
1679
|
+
export { src_default as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-flawless",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Your ESLint plugin description",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -34,44 +34,45 @@
|
|
|
34
34
|
"*": "eslint --fix --cache"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@typescript-eslint/scope-manager": "8.
|
|
38
|
-
"@typescript-eslint/type-utils": "
|
|
39
|
-
"@typescript-eslint/utils": "8.
|
|
37
|
+
"@typescript-eslint/scope-manager": "8.62.1",
|
|
38
|
+
"@typescript-eslint/type-utils": "8.62.1",
|
|
39
|
+
"@typescript-eslint/utils": "8.62.1"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@antfu/ni": "
|
|
43
|
-
"@isentinel/eslint-config": "
|
|
44
|
-
"@isentinel/tsconfig": "1.
|
|
42
|
+
"@antfu/ni": "30.2.0",
|
|
43
|
+
"@isentinel/eslint-config": "5.2.0",
|
|
44
|
+
"@isentinel/tsconfig": "1.2.0",
|
|
45
45
|
"@types/node": "24.0.13",
|
|
46
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
47
|
-
"@typescript-eslint/parser": "8.
|
|
48
|
-
"@vitest/eslint-plugin": "1.
|
|
49
|
-
"bumpp": "
|
|
50
|
-
"eslint": "9.
|
|
51
|
-
"eslint-doc-generator": "
|
|
52
|
-
"eslint-plugin-eslint-plugin": "7.
|
|
53
|
-
"eslint-plugin-n": "
|
|
54
|
-
"eslint-plugin-pnpm": "1.1
|
|
55
|
-
"eslint-
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
46
|
+
"@typescript-eslint/eslint-plugin": "8.62.1",
|
|
47
|
+
"@typescript-eslint/parser": "8.62.1",
|
|
48
|
+
"@vitest/eslint-plugin": "1.6.20",
|
|
49
|
+
"bumpp": "11.1.0",
|
|
50
|
+
"eslint": "9.39.4",
|
|
51
|
+
"eslint-doc-generator": "3.6.0",
|
|
52
|
+
"eslint-plugin-eslint-plugin": "7.4.1",
|
|
53
|
+
"eslint-plugin-n": "18.2.1",
|
|
54
|
+
"eslint-plugin-pnpm": "1.6.1",
|
|
55
|
+
"eslint-plugin-yml": "3.5.0",
|
|
56
|
+
"eslint-vitest-rule-tester": "3.1.0",
|
|
57
|
+
"jiti": "2.7.0",
|
|
58
|
+
"lint-staged": "17.0.8",
|
|
59
|
+
"publint": "0.3.21",
|
|
59
60
|
"simple-git-hooks": "2.13.1",
|
|
60
|
-
"ts-api-utils": "2.
|
|
61
|
-
"tsdown": "0.
|
|
62
|
-
"tsx": "4.
|
|
63
|
-
"typescript": "
|
|
64
|
-
"unplugin-unused": "0.5.
|
|
65
|
-
"vitest": "
|
|
61
|
+
"ts-api-utils": "2.5.0",
|
|
62
|
+
"tsdown": "0.22.3",
|
|
63
|
+
"tsx": "4.22.4",
|
|
64
|
+
"typescript": "6.0.3",
|
|
65
|
+
"unplugin-unused": "0.5.7",
|
|
66
|
+
"vitest": "4.1.9",
|
|
67
|
+
"yaml-eslint-parser": "2.0.0"
|
|
66
68
|
},
|
|
67
69
|
"peerDependencies": {
|
|
68
70
|
"eslint": ">=9.15.0"
|
|
69
71
|
},
|
|
70
72
|
"engines": {
|
|
71
|
-
"node": ">=
|
|
73
|
+
"node": ">=24.12.0"
|
|
72
74
|
},
|
|
73
75
|
"publishConfig": {
|
|
74
|
-
"access": "public",
|
|
75
76
|
"provenance": true
|
|
76
77
|
},
|
|
77
78
|
"scripts": {
|