pasika 0.10.83 → 0.10.85
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/dist/eslint/pasika/index.d.ts +1 -0
- package/dist/eslint/pasika/index.js +149 -67
- package/package.json +1 -1
|
@@ -3029,6 +3029,31 @@ function stringArguments(node) {
|
|
|
3029
3029
|
}
|
|
3030
3030
|
return [];
|
|
3031
3031
|
}
|
|
3032
|
+
function staticClassLiterals(node) {
|
|
3033
|
+
if (!node) return [];
|
|
3034
|
+
if (node.type === "Literal" && typeof node.value === "string") return [node];
|
|
3035
|
+
if (node.type === "CallExpression") {
|
|
3036
|
+
if (node.callee.type === "Identifier" && node.callee.name === "cn") return [];
|
|
3037
|
+
return node.arguments.flatMap(
|
|
3038
|
+
(argument) => argument.type === "SpreadElement" ? [] : staticClassLiterals(argument)
|
|
3039
|
+
);
|
|
3040
|
+
}
|
|
3041
|
+
if (node.type === "ObjectExpression") {
|
|
3042
|
+
return node.properties.flatMap(
|
|
3043
|
+
(property) => property.type === "Property" ? staticClassLiterals(property.value) : []
|
|
3044
|
+
);
|
|
3045
|
+
}
|
|
3046
|
+
if (node.type === "ArrayExpression") {
|
|
3047
|
+
return node.elements.flatMap((element) => element?.type === "SpreadElement" ? [] : staticClassLiterals(element));
|
|
3048
|
+
}
|
|
3049
|
+
if (node.type === "ConditionalExpression") {
|
|
3050
|
+
return [...staticClassLiterals(node.consequent), ...staticClassLiterals(node.alternate)];
|
|
3051
|
+
}
|
|
3052
|
+
if (node.type === "LogicalExpression") {
|
|
3053
|
+
return [...staticClassLiterals(node.left), ...staticClassLiterals(node.right)];
|
|
3054
|
+
}
|
|
3055
|
+
return [];
|
|
3056
|
+
}
|
|
3032
3057
|
var enforceCnMergeRule = {
|
|
3033
3058
|
meta: { schema: [], type: "problem", docs: { description: "Enforce cn() for conditional class merging." } },
|
|
3034
3059
|
create(context) {
|
|
@@ -3042,6 +3067,32 @@ var enforceCnMergeRule = {
|
|
|
3042
3067
|
}
|
|
3043
3068
|
}
|
|
3044
3069
|
return {
|
|
3070
|
+
CallExpression(node) {
|
|
3071
|
+
if (node.callee.type !== "Identifier") return;
|
|
3072
|
+
if (node.callee.name === "cn") {
|
|
3073
|
+
for (const argument of node.arguments) {
|
|
3074
|
+
if (argument.type !== "Literal" || typeof argument.value !== "string" || classCount(argument.value) <= 5) {
|
|
3075
|
+
continue;
|
|
3076
|
+
}
|
|
3077
|
+
context.report({
|
|
3078
|
+
node: argument,
|
|
3079
|
+
message: "Each cn() string argument must contain at most 5 class names. Group by styling concern. See docs/next-tailwind-guide/rules/class-composition-rule.md"
|
|
3080
|
+
});
|
|
3081
|
+
}
|
|
3082
|
+
return;
|
|
3083
|
+
}
|
|
3084
|
+
if (node.callee.name !== "cva") return;
|
|
3085
|
+
for (const argument of node.arguments) {
|
|
3086
|
+
if (argument.type === "SpreadElement") continue;
|
|
3087
|
+
for (const literal of staticClassLiterals(argument)) {
|
|
3088
|
+
if (typeof literal.value !== "string" || classCount(literal.value) <= 5) continue;
|
|
3089
|
+
context.report({
|
|
3090
|
+
node: literal,
|
|
3091
|
+
message: "Static cva class list with more than 5 classes must use cn() with grouped string literals. See docs/next-tailwind-guide/rules/class-composition-rule.md"
|
|
3092
|
+
});
|
|
3093
|
+
}
|
|
3094
|
+
}
|
|
3095
|
+
},
|
|
3045
3096
|
JSXAttribute(node) {
|
|
3046
3097
|
const attributeName = node.name?.name ?? "";
|
|
3047
3098
|
const element = node.parent.parent;
|
|
@@ -3107,17 +3158,6 @@ var enforceCnMergeRule = {
|
|
|
3107
3158
|
node,
|
|
3108
3159
|
message: "Static className with more than 5 classes must use cn() with grouped string literals. See docs/next-tailwind-guide/rules/class-composition-rule.md"
|
|
3109
3160
|
});
|
|
3110
|
-
return;
|
|
3111
|
-
}
|
|
3112
|
-
if (expr.type === "CallExpression" && expr.callee.type === "Identifier" && expr.callee.name === "cn") {
|
|
3113
|
-
for (const arg of expr.arguments) {
|
|
3114
|
-
if (arg.type === "Literal" && typeof arg.value === "string" && classCount(arg.value) > 5) {
|
|
3115
|
-
context.report({
|
|
3116
|
-
node: arg,
|
|
3117
|
-
message: "Each cn() string argument must contain at most 5 class names. Group by styling concern. See docs/next-tailwind-guide/rules/class-composition-rule.md"
|
|
3118
|
-
});
|
|
3119
|
-
}
|
|
3120
|
-
}
|
|
3121
3161
|
}
|
|
3122
3162
|
}
|
|
3123
3163
|
};
|
|
@@ -6181,14 +6221,16 @@ var preferEnumRule = {
|
|
|
6181
6221
|
};
|
|
6182
6222
|
|
|
6183
6223
|
// eslint/rules/prefer-object-destructuring.ts
|
|
6224
|
+
import ts8 from "typescript";
|
|
6184
6225
|
var DOC5 = "See docs/next-codebase-guide/rules/redundant-aliases-rule.md";
|
|
6185
6226
|
function hasTypeAnnotation(identifier) {
|
|
6186
6227
|
return "typeAnnotation" in identifier && identifier.typeAnnotation !== void 0;
|
|
6187
6228
|
}
|
|
6188
|
-
function directPropertyBinding(context, declarator) {
|
|
6229
|
+
function directPropertyBinding(context, declarator, isEnumValue) {
|
|
6189
6230
|
if (declarator.id.type !== "Identifier" || hasTypeAnnotation(declarator.id)) return void 0;
|
|
6190
6231
|
if (declarator.init?.type !== "MemberExpression") return void 0;
|
|
6191
6232
|
const member = declarator.init;
|
|
6233
|
+
if (isEnumValue(member.object)) return void 0;
|
|
6192
6234
|
if (member.computed || member.optional || member.property.type !== "Identifier") return void 0;
|
|
6193
6235
|
if (!memberCanBecomeLocal(member)) return void 0;
|
|
6194
6236
|
if (context.sourceCode.getCommentsInside(declarator).length > 0) return void 0;
|
|
@@ -6249,6 +6291,37 @@ function memberCanBecomeLocal(member) {
|
|
|
6249
6291
|
if (rootIdentifierName(member) === "locales") return false;
|
|
6250
6292
|
return member.property.type === "Identifier" && isCompliantLocalName(member.property.name);
|
|
6251
6293
|
}
|
|
6294
|
+
function isEnumDefinition(definition) {
|
|
6295
|
+
return typeof definition === "object" && definition !== null && "type" in definition && definition.type === "TSEnumName";
|
|
6296
|
+
}
|
|
6297
|
+
function localEnumBinding(context, node) {
|
|
6298
|
+
if (node.type !== "Identifier") return false;
|
|
6299
|
+
let scope = context.sourceCode.getScope(node);
|
|
6300
|
+
for (; ; ) {
|
|
6301
|
+
const variable = scope.variables.find(({ name }) => name === node.name);
|
|
6302
|
+
if (variable) return variable.defs.some(isEnumDefinition);
|
|
6303
|
+
if (scope.upper === null) return false;
|
|
6304
|
+
scope = scope.upper;
|
|
6305
|
+
}
|
|
6306
|
+
}
|
|
6307
|
+
function enumValueResolver(context) {
|
|
6308
|
+
const services = typedParserServices(context.sourceCode.parserServices);
|
|
6309
|
+
if (!services) return (node) => localEnumBinding(context, node);
|
|
6310
|
+
const checker = services.program.getTypeChecker();
|
|
6311
|
+
const { esTreeNodeToTSNodeMap: nodeMap } = services;
|
|
6312
|
+
const isEnumSymbol = (symbol) => {
|
|
6313
|
+
const resolved = symbol.flags === ts8.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
|
|
6314
|
+
return (resolved.declarations ?? []).some((declaration) => ts8.isEnumDeclaration(declaration));
|
|
6315
|
+
};
|
|
6316
|
+
return (node) => {
|
|
6317
|
+
const tsNode = nodeMap.get(node);
|
|
6318
|
+
if (!tsNode) return localEnumBinding(context, node);
|
|
6319
|
+
const symbol = checker.getSymbolAtLocation(tsNode);
|
|
6320
|
+
if (symbol && isEnumSymbol(symbol)) return true;
|
|
6321
|
+
const typeSymbol = checker.getTypeAtLocation(tsNode).getSymbol();
|
|
6322
|
+
return typeSymbol ? isEnumSymbol(typeSymbol) : localEnumBinding(context, node);
|
|
6323
|
+
};
|
|
6324
|
+
}
|
|
6252
6325
|
function directMappingRequiresQualifiedAccess(context, ownershipResolver, member) {
|
|
6253
6326
|
const mapping = renamedDirectMapping(context, member);
|
|
6254
6327
|
if (!mapping || !ownershipResolver) return false;
|
|
@@ -6256,8 +6329,8 @@ function directMappingRequiresQualifiedAccess(context, ownershipResolver, member
|
|
|
6256
6329
|
const targetResolution = ownershipResolver.targetProperty(mapping.property, mapping.targetName);
|
|
6257
6330
|
return sourceResolution.kind === "data-contract" || targetResolution.kind === "data-contract";
|
|
6258
6331
|
}
|
|
6259
|
-
function memberCanBeDestructured(context, ownershipResolver, member) {
|
|
6260
|
-
return memberCanBecomeLocal(member) && !directMappingRequiresQualifiedAccess(context, ownershipResolver, member);
|
|
6332
|
+
function memberCanBeDestructured(context, ownershipResolver, member, isEnumValue) {
|
|
6333
|
+
return !isEnumValue(member.object) && memberCanBecomeLocal(member) && !directMappingRequiresQualifiedAccess(context, ownershipResolver, member);
|
|
6261
6334
|
}
|
|
6262
6335
|
function objectUsage(scope, sourceText) {
|
|
6263
6336
|
let usage = scope.objects.get(sourceText);
|
|
@@ -6282,9 +6355,9 @@ function memberIsDirectVariableInitializer(context, member) {
|
|
|
6282
6355
|
const parent = context.sourceCode.getAncestors(member).at(-1);
|
|
6283
6356
|
return parent?.type === "VariableDeclarator" && parent.init === member;
|
|
6284
6357
|
}
|
|
6285
|
-
function recordMemberUsage(context, scope, ownershipResolver, member) {
|
|
6358
|
+
function recordMemberUsage(context, scope, ownershipResolver, member, isEnumValue) {
|
|
6286
6359
|
if (!scope || member.computed || member.optional || member.property.type !== "Identifier") return;
|
|
6287
|
-
if (!memberCanBeDestructured(context, ownershipResolver, member)) return;
|
|
6360
|
+
if (!memberCanBeDestructured(context, ownershipResolver, member, isEnumValue)) return;
|
|
6288
6361
|
if (!isGroupedUsageSource(member.object) || !memberIsRead(context, member)) return;
|
|
6289
6362
|
const sourceText = context.sourceCode.getText(member.object);
|
|
6290
6363
|
const usage = objectUsage(scope, sourceText);
|
|
@@ -6294,11 +6367,11 @@ function recordMemberUsage(context, scope, ownershipResolver, member) {
|
|
|
6294
6367
|
usage.directMembers.push({ member, propertyName: propertyName5 });
|
|
6295
6368
|
}
|
|
6296
6369
|
}
|
|
6297
|
-
function recordDestructuringUsage(context, scope, declaration) {
|
|
6370
|
+
function recordDestructuringUsage(context, scope, declaration, isEnumValue) {
|
|
6298
6371
|
if (!scope) return;
|
|
6299
6372
|
for (const declarator of declaration.declarations) {
|
|
6300
6373
|
if (declarator.id.type !== "ObjectPattern" || !declarator.init || !isGroupedUsageSource(declarator.init)) continue;
|
|
6301
|
-
if (rootIdentifierName(declarator.init) === "locales") continue;
|
|
6374
|
+
if (rootIdentifierName(declarator.init) === "locales" || isEnumValue(declarator.init)) continue;
|
|
6302
6375
|
const sourceText = context.sourceCode.getText(declarator.init);
|
|
6303
6376
|
const usage = objectUsage(scope, sourceText);
|
|
6304
6377
|
if (usage.directMembers.length > 0) continue;
|
|
@@ -6345,7 +6418,7 @@ function whitespaceKeepsStatementsAdjacent(text) {
|
|
|
6345
6418
|
if (text.trim() !== "") return false;
|
|
6346
6419
|
return (text.match(/\n/gu) ?? []).length <= 1;
|
|
6347
6420
|
}
|
|
6348
|
-
function groupedDeclarations(context, declaration, firstBinding) {
|
|
6421
|
+
function groupedDeclarations(context, declaration, firstBinding, isEnumValue) {
|
|
6349
6422
|
if (declaration.declarations.length !== 1) {
|
|
6350
6423
|
return [{ declaration, binding: firstBinding }];
|
|
6351
6424
|
}
|
|
@@ -6365,7 +6438,7 @@ function groupedDeclarations(context, declaration, firstBinding) {
|
|
|
6365
6438
|
if (nextNode.declarations.length !== 1) break;
|
|
6366
6439
|
const nextDeclarator = nextNode.declarations[0];
|
|
6367
6440
|
if (!nextDeclarator) break;
|
|
6368
|
-
const nextBinding = directPropertyBinding(context, nextDeclarator);
|
|
6441
|
+
const nextBinding = directPropertyBinding(context, nextDeclarator, isEnumValue);
|
|
6369
6442
|
if (nextBinding?.sourceText !== firstBinding.sourceText) break;
|
|
6370
6443
|
if (seenProperties.has(nextBinding.propertyName)) break;
|
|
6371
6444
|
const [, previousEnd] = context.sourceCode.getRange(previous);
|
|
@@ -6377,11 +6450,11 @@ function groupedDeclarations(context, declaration, firstBinding) {
|
|
|
6377
6450
|
}
|
|
6378
6451
|
return group;
|
|
6379
6452
|
}
|
|
6380
|
-
function destructuringSelection(context, declaration) {
|
|
6453
|
+
function destructuringSelection(context, declaration, isEnumValue) {
|
|
6381
6454
|
if (declaration.declarations.length !== 1) return void 0;
|
|
6382
6455
|
const declarator = declaration.declarations[0];
|
|
6383
6456
|
if (declarator?.id.type !== "ObjectPattern" || !declarator.init) return void 0;
|
|
6384
|
-
if (rootIdentifierName(declarator.init) === "locales") return void 0;
|
|
6457
|
+
if (rootIdentifierName(declarator.init) === "locales" || isEnumValue(declarator.init)) return void 0;
|
|
6385
6458
|
if (context.sourceCode.getCommentsInside(declarator).length > 0) return void 0;
|
|
6386
6459
|
const bindingTexts = [];
|
|
6387
6460
|
const localNames = [];
|
|
@@ -6404,7 +6477,7 @@ function destructuringSelection(context, declaration) {
|
|
|
6404
6477
|
propertyNames
|
|
6405
6478
|
};
|
|
6406
6479
|
}
|
|
6407
|
-
function groupedDestructuringSelections(context, first) {
|
|
6480
|
+
function groupedDestructuringSelections(context, first, isEnumValue) {
|
|
6408
6481
|
const parent = context.sourceCode.getAncestors(first.declaration).at(-1);
|
|
6409
6482
|
if (parent?.type !== "Program" && parent?.type !== "BlockStatement") return [first];
|
|
6410
6483
|
const body = parent.body;
|
|
@@ -6416,7 +6489,7 @@ function groupedDestructuringSelections(context, first) {
|
|
|
6416
6489
|
const nextNode = body[index];
|
|
6417
6490
|
const previous = group.at(-1)?.declaration;
|
|
6418
6491
|
if (!previous || nextNode?.type !== "VariableDeclaration" || nextNode.kind !== first.declaration.kind) break;
|
|
6419
|
-
const next = destructuringSelection(context, nextNode);
|
|
6492
|
+
const next = destructuringSelection(context, nextNode, isEnumValue);
|
|
6420
6493
|
if (next?.sourceText !== first.sourceText) break;
|
|
6421
6494
|
if (next.propertyNames.some((propertyName5) => seenProperties.has(propertyName5))) break;
|
|
6422
6495
|
const [, previousEnd] = context.sourceCode.getRange(previous);
|
|
@@ -6457,6 +6530,7 @@ var preferObjectDestructuringRule = {
|
|
|
6457
6530
|
},
|
|
6458
6531
|
create(context) {
|
|
6459
6532
|
const ownershipResolver = contractOwnershipResolver(context);
|
|
6533
|
+
const isEnumValue = enumValueResolver(context);
|
|
6460
6534
|
const grouped = /* @__PURE__ */ new Set();
|
|
6461
6535
|
const usageScopes = [];
|
|
6462
6536
|
const currentUsageScope = () => usageScopes.at(-1);
|
|
@@ -6521,14 +6595,22 @@ ${indentation}`;
|
|
|
6521
6595
|
ArrowFunctionExpression: enterUsageBarrier,
|
|
6522
6596
|
"ArrowFunctionExpression:exit": exitUsageScope,
|
|
6523
6597
|
MemberExpression(node) {
|
|
6524
|
-
recordMemberUsage(context, currentUsageScope(), ownershipResolver, node);
|
|
6598
|
+
recordMemberUsage(context, currentUsageScope(), ownershipResolver, node, isEnumValue);
|
|
6525
6599
|
},
|
|
6526
6600
|
VariableDeclaration(node) {
|
|
6527
|
-
|
|
6601
|
+
for (const declarator of node.declarations) {
|
|
6602
|
+
if (declarator.id.type !== "ObjectPattern" || !declarator.init || !isEnumValue(declarator.init)) continue;
|
|
6603
|
+
const sourceText = context.sourceCode.getText(declarator.init);
|
|
6604
|
+
context.report({
|
|
6605
|
+
node: declarator.id,
|
|
6606
|
+
message: `"${sourceText}" is an enum. Keep enum member accesses qualified instead of destructuring it. ${DOC5}`
|
|
6607
|
+
});
|
|
6608
|
+
}
|
|
6609
|
+
recordDestructuringUsage(context, currentUsageScope(), node, isEnumValue);
|
|
6528
6610
|
if (grouped.has(node)) return;
|
|
6529
|
-
const selection = destructuringSelection(context, node);
|
|
6611
|
+
const selection = destructuringSelection(context, node, isEnumValue);
|
|
6530
6612
|
if (selection) {
|
|
6531
|
-
const group = groupedDestructuringSelections(context, selection);
|
|
6613
|
+
const group = groupedDestructuringSelections(context, selection, isEnumValue);
|
|
6532
6614
|
if (group.length <= 1) return;
|
|
6533
6615
|
for (const item of group.slice(1)) grouped.add(item.declaration);
|
|
6534
6616
|
const lastDeclaration = group.at(-1)?.declaration;
|
|
@@ -6550,7 +6632,7 @@ ${indentation}`;
|
|
|
6550
6632
|
});
|
|
6551
6633
|
return;
|
|
6552
6634
|
}
|
|
6553
|
-
const bindings = node.declarations.map((declarator) => directPropertyBinding(context, declarator)).filter((binding) => binding !== void 0);
|
|
6635
|
+
const bindings = node.declarations.map((declarator) => directPropertyBinding(context, declarator, isEnumValue)).filter((binding) => binding !== void 0);
|
|
6554
6636
|
if (bindings.length === 0) return;
|
|
6555
6637
|
const firstBinding = bindings[0];
|
|
6556
6638
|
if (!firstBinding) return;
|
|
@@ -6571,7 +6653,7 @@ ${indentation}`;
|
|
|
6571
6653
|
return;
|
|
6572
6654
|
}
|
|
6573
6655
|
if (node.declarations.length === 1 && bindings.length === 1) {
|
|
6574
|
-
const group = groupedDeclarations(context, node, firstBinding);
|
|
6656
|
+
const group = groupedDeclarations(context, node, firstBinding, isEnumValue);
|
|
6575
6657
|
if (group.length > 1) {
|
|
6576
6658
|
for (const item of group.slice(1)) grouped.add(item.declaration);
|
|
6577
6659
|
const groupBindings = group.map(({ binding }) => binding);
|
|
@@ -7144,7 +7226,7 @@ var rootSupportPlacementRule = {
|
|
|
7144
7226
|
|
|
7145
7227
|
// eslint/rules/route-handler-shape.ts
|
|
7146
7228
|
import path48 from "path";
|
|
7147
|
-
import
|
|
7229
|
+
import ts9 from "typescript";
|
|
7148
7230
|
var HTTP_METHODS2 = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
7149
7231
|
var REQUIRED_BOUNDARY = "withResponse";
|
|
7150
7232
|
function isFunctionLike(node) {
|
|
@@ -7162,33 +7244,33 @@ function findHandler(node) {
|
|
|
7162
7244
|
return void 0;
|
|
7163
7245
|
}
|
|
7164
7246
|
function isLoop(node) {
|
|
7165
|
-
return
|
|
7247
|
+
return ts9.isForStatement(node) || ts9.isForOfStatement(node) || ts9.isForInStatement(node) || ts9.isWhileStatement(node) || ts9.isDoStatement(node);
|
|
7166
7248
|
}
|
|
7167
7249
|
function isFunctionBoundary(node) {
|
|
7168
|
-
return
|
|
7250
|
+
return ts9.isFunctionExpression(node) || ts9.isArrowFunction(node) || ts9.isFunctionDeclaration(node);
|
|
7169
7251
|
}
|
|
7170
7252
|
function analyzeHandlerBody(body, sourceText) {
|
|
7171
7253
|
const start = body.range?.[0] ?? 0;
|
|
7172
7254
|
const end = body.range?.[1] ?? sourceText.length;
|
|
7173
|
-
const sourceFile =
|
|
7255
|
+
const sourceFile = ts9.createSourceFile(
|
|
7174
7256
|
"route.ts",
|
|
7175
7257
|
sourceText.slice(start, end),
|
|
7176
|
-
|
|
7258
|
+
ts9.ScriptTarget.Latest,
|
|
7177
7259
|
true,
|
|
7178
|
-
|
|
7260
|
+
ts9.ScriptKind.TS
|
|
7179
7261
|
);
|
|
7180
7262
|
const kinds = /* @__PURE__ */ new Set();
|
|
7181
7263
|
const calledNames = /* @__PURE__ */ new Set();
|
|
7182
7264
|
const visit = (node) => {
|
|
7183
|
-
if (
|
|
7265
|
+
if (ts9.isTryStatement(node)) kinds.add("try");
|
|
7184
7266
|
if (isLoop(node)) kinds.add("loop");
|
|
7185
|
-
if (
|
|
7186
|
-
if (
|
|
7267
|
+
if (ts9.isIfStatement(node)) kinds.add("if");
|
|
7268
|
+
if (ts9.isCallExpression(node) && ts9.isPropertyAccessExpression(node.expression) && node.expression.name.text === "map") {
|
|
7187
7269
|
kinds.add("map");
|
|
7188
7270
|
}
|
|
7189
|
-
if (
|
|
7271
|
+
if (ts9.isCallExpression(node) && ts9.isIdentifier(node.expression)) calledNames.add(node.expression.text);
|
|
7190
7272
|
if (isFunctionBoundary(node)) return;
|
|
7191
|
-
|
|
7273
|
+
ts9.forEachChild(node, visit);
|
|
7192
7274
|
};
|
|
7193
7275
|
visit(sourceFile);
|
|
7194
7276
|
return { kinds, calledNames };
|
|
@@ -7350,38 +7432,38 @@ var schemaCasingRule = {
|
|
|
7350
7432
|
|
|
7351
7433
|
// eslint/rules/sole-state-owner.ts
|
|
7352
7434
|
import path50 from "path";
|
|
7353
|
-
import
|
|
7435
|
+
import ts10 from "typescript";
|
|
7354
7436
|
function findStateHooks(node) {
|
|
7355
7437
|
const hooks = [];
|
|
7356
7438
|
const visit = (child) => {
|
|
7357
|
-
if (
|
|
7358
|
-
if (
|
|
7439
|
+
if (ts10.isCallExpression(child) && ts10.isIdentifier(child.expression) && child.expression.text === "useState") {
|
|
7440
|
+
if (ts10.isVariableDeclaration(child.parent)) {
|
|
7359
7441
|
const { name } = child.parent;
|
|
7360
|
-
if (
|
|
7442
|
+
if (ts10.isArrayBindingPattern(name) && name.elements.length >= 2) {
|
|
7361
7443
|
const value = name.elements[0];
|
|
7362
7444
|
const updater = name.elements[1];
|
|
7363
|
-
if (value && updater &&
|
|
7445
|
+
if (value && updater && ts10.isBindingElement(value) && ts10.isBindingElement(updater)) {
|
|
7364
7446
|
const valueName = value.name;
|
|
7365
7447
|
const updaterName = updater.name;
|
|
7366
|
-
if (
|
|
7448
|
+
if (ts10.isIdentifier(valueName) && ts10.isIdentifier(updaterName)) {
|
|
7367
7449
|
hooks.push({ value: valueName.text, updater: updaterName.text });
|
|
7368
7450
|
}
|
|
7369
7451
|
}
|
|
7370
7452
|
}
|
|
7371
7453
|
}
|
|
7372
7454
|
}
|
|
7373
|
-
|
|
7455
|
+
ts10.forEachChild(child, visit);
|
|
7374
7456
|
};
|
|
7375
7457
|
visit(node);
|
|
7376
7458
|
return hooks;
|
|
7377
7459
|
}
|
|
7378
7460
|
function isHookUsage(node, hook) {
|
|
7379
|
-
if (
|
|
7461
|
+
if (ts10.isCallExpression(node) && ts10.isIdentifier(node.expression) && node.expression.text === hook.updater) {
|
|
7380
7462
|
return "updater";
|
|
7381
7463
|
}
|
|
7382
|
-
if (
|
|
7464
|
+
if (ts10.isIdentifier(node) && node.text === hook.value) {
|
|
7383
7465
|
const parent = node.parent;
|
|
7384
|
-
if (
|
|
7466
|
+
if (ts10.isBindingElement(parent) || ts10.isPropertyAccessExpression(parent) || ts10.isShorthandPropertyAssignment(parent)) {
|
|
7385
7467
|
return void 0;
|
|
7386
7468
|
}
|
|
7387
7469
|
return "value";
|
|
@@ -7391,16 +7473,16 @@ function isHookUsage(node, hook) {
|
|
|
7391
7473
|
function topLevelJsxChildren(initial) {
|
|
7392
7474
|
if (!initial) return void 0;
|
|
7393
7475
|
let expression = initial;
|
|
7394
|
-
while (
|
|
7395
|
-
if (
|
|
7476
|
+
while (ts10.isParenthesizedExpression(expression)) expression = expression.expression;
|
|
7477
|
+
if (ts10.isJsxFragment(expression)) {
|
|
7396
7478
|
const children = expression.children.filter(
|
|
7397
|
-
(c) => !
|
|
7479
|
+
(c) => !ts10.isJsxText(c) && !ts10.isJsxSpreadAttribute(c)
|
|
7398
7480
|
);
|
|
7399
7481
|
return { root: expression, children };
|
|
7400
7482
|
}
|
|
7401
|
-
if (
|
|
7483
|
+
if (ts10.isJsxElement(expression)) {
|
|
7402
7484
|
const children = expression.children.filter(
|
|
7403
|
-
(c) => !
|
|
7485
|
+
(c) => !ts10.isJsxText(c) && !ts10.isJsxSpreadAttribute(c)
|
|
7404
7486
|
);
|
|
7405
7487
|
return { root: expression, children };
|
|
7406
7488
|
}
|
|
@@ -7414,8 +7496,8 @@ function collectUsesIn(child, hook) {
|
|
|
7414
7496
|
positions.push(node);
|
|
7415
7497
|
count += 1;
|
|
7416
7498
|
}
|
|
7417
|
-
if (
|
|
7418
|
-
|
|
7499
|
+
if (ts10.isFunctionDeclaration(node) || ts10.isClassDeclaration(node)) return;
|
|
7500
|
+
ts10.forEachChild(node, visit);
|
|
7419
7501
|
};
|
|
7420
7502
|
visit(child);
|
|
7421
7503
|
return { positions, count };
|
|
@@ -7454,18 +7536,18 @@ var soleStateOwnerRule = {
|
|
|
7454
7536
|
}
|
|
7455
7537
|
};
|
|
7456
7538
|
function analyzeSoleOwner(declaration, hook) {
|
|
7457
|
-
const body =
|
|
7458
|
-
if (!body || !
|
|
7539
|
+
const body = ts10.isFunctionDeclaration(declaration) ? declaration.body : void 0;
|
|
7540
|
+
if (!body || !ts10.isBlock(body)) return void 0;
|
|
7459
7541
|
const returns = [];
|
|
7460
7542
|
const visit = (node) => {
|
|
7461
|
-
if (node !== body && (
|
|
7462
|
-
if (
|
|
7463
|
-
|
|
7543
|
+
if (node !== body && (ts10.isFunctionLike(node) || ts10.isClassLike(node))) return;
|
|
7544
|
+
if (ts10.isReturnStatement(node)) returns.push(node);
|
|
7545
|
+
ts10.forEachChild(node, visit);
|
|
7464
7546
|
};
|
|
7465
7547
|
visit(body);
|
|
7466
7548
|
if (returns.length !== 1) return void 0;
|
|
7467
7549
|
const single = returns[0];
|
|
7468
|
-
if (!single?.expression || !
|
|
7550
|
+
if (!single?.expression || !ts10.isExpression(single.expression)) return void 0;
|
|
7469
7551
|
const returnExpression = single.expression;
|
|
7470
7552
|
const root = topLevelJsxChildren(returnExpression);
|
|
7471
7553
|
if (!root || root.children.length === 0) return void 0;
|
|
@@ -7488,11 +7570,11 @@ function usesOutsideJsx(declaration, hook, children) {
|
|
|
7488
7570
|
let outside = false;
|
|
7489
7571
|
const visit = (node) => {
|
|
7490
7572
|
if (outside) return;
|
|
7491
|
-
if (node !== declaration && (
|
|
7573
|
+
if (node !== declaration && (ts10.isFunctionDeclaration(node) || ts10.isClassDeclaration(node))) return;
|
|
7492
7574
|
if (isHookUsage(node, hook)) {
|
|
7493
7575
|
let current = node;
|
|
7494
7576
|
let isInJsxChild = false;
|
|
7495
|
-
while (!
|
|
7577
|
+
while (!ts10.isSourceFile(current)) {
|
|
7496
7578
|
if (children.includes(current)) {
|
|
7497
7579
|
isInJsxChild = true;
|
|
7498
7580
|
break;
|
|
@@ -7501,7 +7583,7 @@ function usesOutsideJsx(declaration, hook, children) {
|
|
|
7501
7583
|
}
|
|
7502
7584
|
if (!isInJsxChild) outside = true;
|
|
7503
7585
|
}
|
|
7504
|
-
|
|
7586
|
+
ts10.forEachChild(node, visit);
|
|
7505
7587
|
};
|
|
7506
7588
|
visit(declaration);
|
|
7507
7589
|
return outside;
|