@zgeoff/oxlint-config 0.2.10 → 0.2.11
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 +13 -5
- package/no-abbreviated-names.js +133 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -109,11 +109,19 @@ the paths that may name the words:
|
|
|
109
109
|
|
|
110
110
|
## `zgeoff/no-abbreviated-names`
|
|
111
111
|
|
|
112
|
-
The `names` option maps each abbreviation to the text that replaces it, and the rule reports
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
112
|
+
The `names` option maps each abbreviation to the text that replaces it, and the rule reports every
|
|
113
|
+
value name that has one of those names. A value name is any name that a declaration, an import, an
|
|
114
|
+
export alias, a key or a member write binds, so function, class and method names count beside
|
|
115
|
+
variables and properties. A key counts in each of its spellings, so `src`, `'src'`, `['src']` and
|
|
116
|
+
`#src` all report. A name matches whole, so `ms` reports `ms` but not `timeoutMs`.
|
|
117
|
+
|
|
118
|
+
The rule leaves alone the names that hold no value of their own. A destructured key that an alias
|
|
119
|
+
renames belongs to the object being read, so the rule reports only the alias. A computed key that
|
|
120
|
+
reads a variable, such as `[src]`, names no property, and the rule checks the variable at its
|
|
121
|
+
declaration. Type names, type-only imports and exports, labels and quoted module names hold no
|
|
122
|
+
value, so the rule skips them.
|
|
123
|
+
|
|
124
|
+
The shipped config lists the abbreviations that the code-style skill bans and turns on `id-length`
|
|
117
125
|
beside the rule, so a one-letter name fails too, other than `x`, `y`, `z`, `$` and `_`.
|
|
118
126
|
|
|
119
127
|
## `zgeoff/no-file-snapshot`
|
package/no-abbreviated-names.js
CHANGED
|
@@ -25,9 +25,9 @@ const noAbbreviatedNames = {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
const checkName = (node) => {
|
|
28
|
-
const
|
|
28
|
+
const name = findStaticName(node);
|
|
29
29
|
|
|
30
|
-
if (
|
|
30
|
+
if (name === null || !names.has(name)) {
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -36,7 +36,7 @@ const noAbbreviatedNames = {
|
|
|
36
36
|
context.report({
|
|
37
37
|
node,
|
|
38
38
|
messageId: 'abbreviated',
|
|
39
|
-
data: { name: `${prefix}${
|
|
39
|
+
data: { name: `${prefix}${name}`, replacement: names.get(name) },
|
|
40
40
|
});
|
|
41
41
|
};
|
|
42
42
|
|
|
@@ -46,32 +46,63 @@ const noAbbreviatedNames = {
|
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
// a computed key names its property as a plain key does when it is a
|
|
50
|
+
// string written in place, as in `{ ['src']: 1 }`; a computed identifier
|
|
51
|
+
// reads a variable, whose declaration is checked where it is made
|
|
52
|
+
const checkMemberName = (node, name) => {
|
|
53
|
+
if (!node.computed || name.type !== 'Identifier') {
|
|
54
|
+
checkName(name);
|
|
52
55
|
}
|
|
53
56
|
};
|
|
54
57
|
|
|
58
|
+
const checkKey = (node) => {
|
|
59
|
+
checkMemberName(node, node.key);
|
|
60
|
+
};
|
|
61
|
+
|
|
55
62
|
const checkParams = (node) => {
|
|
56
63
|
for (const param of node.params) {
|
|
57
64
|
checkPattern(param);
|
|
58
65
|
}
|
|
59
66
|
};
|
|
60
67
|
|
|
68
|
+
// a write to a member names that property, whether the member stands
|
|
69
|
+
// alone or sits inside a destructuring target
|
|
70
|
+
const checkAssignmentTarget = (node) => {
|
|
71
|
+
for (const member of collectTargetMembers(node)) {
|
|
72
|
+
checkMemberName(member, member.property);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const checkLoopTarget = (node) => {
|
|
77
|
+
if (node.left.type !== 'VariableDeclaration') {
|
|
78
|
+
checkAssignmentTarget(node.left);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// function-verb checks only a plain function or method name, so a quoted
|
|
83
|
+
// method, a signature or a declared function would pass both rules
|
|
84
|
+
const checkFunction = (node) => {
|
|
85
|
+
checkName(node.id);
|
|
86
|
+
checkParams(node);
|
|
87
|
+
};
|
|
88
|
+
|
|
61
89
|
return {
|
|
62
90
|
VariableDeclarator(node) {
|
|
63
91
|
checkPattern(node.id);
|
|
64
92
|
},
|
|
65
|
-
FunctionDeclaration:
|
|
66
|
-
FunctionExpression:
|
|
93
|
+
FunctionDeclaration: checkFunction,
|
|
94
|
+
FunctionExpression: checkFunction,
|
|
67
95
|
ArrowFunctionExpression: checkParams,
|
|
68
96
|
|
|
69
97
|
// a signature without a body names its parameters as an implementation does
|
|
70
|
-
TSDeclareFunction:
|
|
98
|
+
TSDeclareFunction: checkFunction,
|
|
71
99
|
TSEmptyBodyFunctionExpression: checkParams,
|
|
72
100
|
TSFunctionType: checkParams,
|
|
73
101
|
TSConstructorType: checkParams,
|
|
74
|
-
TSMethodSignature
|
|
102
|
+
TSMethodSignature(node) {
|
|
103
|
+
checkKey(node);
|
|
104
|
+
checkParams(node);
|
|
105
|
+
},
|
|
75
106
|
TSCallSignatureDeclaration: checkParams,
|
|
76
107
|
TSConstructSignatureDeclaration: checkParams,
|
|
77
108
|
CatchClause(node) {
|
|
@@ -83,15 +114,19 @@ const noAbbreviatedNames = {
|
|
|
83
114
|
TSAbstractPropertyDefinition: checkKey,
|
|
84
115
|
TSAbstractAccessorProperty: checkKey,
|
|
85
116
|
TSPropertySignature: checkKey,
|
|
117
|
+
MethodDefinition: checkKey,
|
|
118
|
+
TSAbstractMethodDefinition: checkKey,
|
|
86
119
|
|
|
87
|
-
// a
|
|
88
|
-
// value name
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
120
|
+
// a class, an enum and a namespace are values at run time; a quoted
|
|
121
|
+
// module name is a path, not a value name
|
|
122
|
+
'ClassDeclaration, ClassExpression, TSEnumDeclaration'(node) {
|
|
123
|
+
checkName(node.id);
|
|
124
|
+
},
|
|
125
|
+
TSModuleDeclaration(node) {
|
|
126
|
+
if (node.id.type === 'Identifier') {
|
|
127
|
+
checkName(node.id);
|
|
128
|
+
}
|
|
129
|
+
},
|
|
95
130
|
|
|
96
131
|
// an import's local binding is a value name in this module, whatever the
|
|
97
132
|
// exporting module calls it; a type-only import names a type, not a value
|
|
@@ -105,19 +140,96 @@ const noAbbreviatedNames = {
|
|
|
105
140
|
checkName(node.id);
|
|
106
141
|
}
|
|
107
142
|
},
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
checkName(
|
|
143
|
+
TSIndexSignature(node) {
|
|
144
|
+
for (const parameter of node.parameters) {
|
|
145
|
+
checkName(parameter);
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
TSEnumMember(node) {
|
|
149
|
+
checkName(node.id);
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
// an export alias is the name every importing module reads the value by
|
|
153
|
+
ExportSpecifier(node) {
|
|
154
|
+
if (!isTypeOnlyExport(node)) {
|
|
155
|
+
checkName(node.exported);
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
ExportAllDeclaration(node) {
|
|
159
|
+
if (node.exportKind !== 'type') {
|
|
160
|
+
checkName(node.exported);
|
|
111
161
|
}
|
|
112
162
|
},
|
|
163
|
+
AssignmentExpression(node) {
|
|
164
|
+
checkAssignmentTarget(node.left);
|
|
165
|
+
},
|
|
166
|
+
ForInStatement: checkLoopTarget,
|
|
167
|
+
ForOfStatement: checkLoopTarget,
|
|
113
168
|
};
|
|
114
169
|
},
|
|
115
170
|
};
|
|
116
171
|
|
|
172
|
+
// the name a key or binding spells out in the source: an identifier, a
|
|
173
|
+
// string, or a template with no substitutions; a key built at run time has
|
|
174
|
+
// no static name, so the result is null
|
|
175
|
+
function findStaticName(node) {
|
|
176
|
+
if (node?.type === 'Identifier' || node?.type === 'PrivateIdentifier') {
|
|
177
|
+
return node.name;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (node?.type === 'Literal' && typeof node.value === 'string') {
|
|
181
|
+
return node.value;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (node?.type === 'TemplateLiteral' && node.expressions.length === 0) {
|
|
185
|
+
return node.quasis[0].value.cooked ?? null;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
|
|
117
191
|
function isTypeOnlyImport(specifier) {
|
|
118
192
|
return specifier.importKind === 'type' || specifier.parent.importKind === 'type';
|
|
119
193
|
}
|
|
120
194
|
|
|
195
|
+
function isTypeOnlyExport(specifier) {
|
|
196
|
+
return specifier.exportKind === 'type' || specifier.parent.exportKind === 'type';
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// the members an assignment target writes; a bare identifier in the target
|
|
200
|
+
// writes a variable declared elsewhere, and its declaration is checked there
|
|
201
|
+
function collectTargetMembers(node) {
|
|
202
|
+
if (node === null || node === undefined) {
|
|
203
|
+
return [];
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (node.type === 'MemberExpression') {
|
|
207
|
+
return [node];
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (node.type === 'ObjectPattern') {
|
|
211
|
+
return node.properties.flatMap((property) => {
|
|
212
|
+
const target = property.type === 'RestElement' ? property : property.value;
|
|
213
|
+
|
|
214
|
+
return collectTargetMembers(target);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (node.type === 'ArrayPattern') {
|
|
219
|
+
return node.elements.flatMap((element) => collectTargetMembers(element));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (node.type === 'AssignmentPattern') {
|
|
223
|
+
return collectTargetMembers(node.left);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (node.type === 'RestElement') {
|
|
227
|
+
return collectTargetMembers(node.argument);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return [];
|
|
231
|
+
}
|
|
232
|
+
|
|
121
233
|
// the names a binding pattern declares: a destructured key's alias, not the
|
|
122
234
|
// key, since the key belongs to the object being read
|
|
123
235
|
function collectPatternIdentifiers(node) {
|