@taiga-ui/eslint-plugin-experience-next 0.501.0 → 0.502.0
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/index.esm.js +249 -41
- package/package.json +1 -1
package/index.esm.js
CHANGED
|
@@ -247667,8 +247667,8 @@ function getTypeAwareRuleContext(context) {
|
|
|
247667
247667
|
|
|
247668
247668
|
const importGraphCacheByProgram = new WeakMap();
|
|
247669
247669
|
const defaultExportCacheByProgram = new WeakMap();
|
|
247670
|
+
const fallbackResolutionByProgram = new WeakMap();
|
|
247670
247671
|
const moduleExportNamesCache = new WeakMap();
|
|
247671
|
-
const resolutionStateByProgram = new WeakMap();
|
|
247672
247672
|
const sourceFileCacheByProgram = new WeakMap();
|
|
247673
247673
|
const codeFileExtensionRegExp = /\.[cm]?[jt]sx?$/;
|
|
247674
247674
|
// Angular DI functions resolve tokens at instantiation time, not at module load time,
|
|
@@ -247689,8 +247689,38 @@ function createCanonicalFileName() {
|
|
|
247689
247689
|
: resolvedFileName.toLowerCase();
|
|
247690
247690
|
};
|
|
247691
247691
|
}
|
|
247692
|
-
function
|
|
247693
|
-
|
|
247692
|
+
function normalizeSlashes(fileName) {
|
|
247693
|
+
return fileName.replaceAll('\\', '/');
|
|
247694
|
+
}
|
|
247695
|
+
function computeRelativeImportPath(fromFile, toFile) {
|
|
247696
|
+
const relative = path.relative(path.dirname(fromFile), toFile);
|
|
247697
|
+
const normalized = normalizeSlashes(relative).replace(codeFileExtensionRegExp, '');
|
|
247698
|
+
return normalized.startsWith('.') ? normalized : `./${normalized}`;
|
|
247699
|
+
}
|
|
247700
|
+
function isProjectCodeFile(sourceFile) {
|
|
247701
|
+
const normalizedFileName = normalizeSlashes(sourceFile.fileName);
|
|
247702
|
+
return (!sourceFile.isDeclarationFile &&
|
|
247703
|
+
codeFileExtensionRegExp.test(normalizedFileName) &&
|
|
247704
|
+
!normalizedFileName.includes('/node_modules/'));
|
|
247705
|
+
}
|
|
247706
|
+
// Returns the module resolution cache that the TypeScript program itself populated during
|
|
247707
|
+
// compilation. Not part of the public ts.Program API but available at runtime on TS 4+.
|
|
247708
|
+
function getProgramResolutionCache(program) {
|
|
247709
|
+
const record = program;
|
|
247710
|
+
const getCache = record['getModuleResolutionCache'];
|
|
247711
|
+
if (typeof getCache !== 'function') {
|
|
247712
|
+
return null;
|
|
247713
|
+
}
|
|
247714
|
+
const cache = getCache.call(program);
|
|
247715
|
+
if (cache === null ||
|
|
247716
|
+
typeof cache !== 'object' ||
|
|
247717
|
+
!('getOrCreateCacheForDirectory' in cache)) {
|
|
247718
|
+
return null;
|
|
247719
|
+
}
|
|
247720
|
+
return cache;
|
|
247721
|
+
}
|
|
247722
|
+
function getFallbackResolution(program) {
|
|
247723
|
+
const cached = fallbackResolutionByProgram.get(program);
|
|
247694
247724
|
if (cached) {
|
|
247695
247725
|
return cached;
|
|
247696
247726
|
}
|
|
@@ -247699,23 +247729,22 @@ function getResolutionState(program) {
|
|
|
247699
247729
|
compilerHost: ts.createCompilerHost(compilerOptions, true),
|
|
247700
247730
|
resolutionCache: ts.createModuleResolutionCache(program.getCurrentDirectory(), (fileName) => fileName, compilerOptions),
|
|
247701
247731
|
};
|
|
247702
|
-
|
|
247732
|
+
fallbackResolutionByProgram.set(program, state);
|
|
247703
247733
|
return state;
|
|
247704
247734
|
}
|
|
247705
|
-
function normalizeSlashes(fileName) {
|
|
247706
|
-
return fileName.replaceAll('\\', '/');
|
|
247707
|
-
}
|
|
247708
|
-
function isProjectCodeFile(sourceFile) {
|
|
247709
|
-
const normalizedFileName = normalizeSlashes(sourceFile.fileName);
|
|
247710
|
-
return (!sourceFile.isDeclarationFile &&
|
|
247711
|
-
codeFileExtensionRegExp.test(normalizedFileName) &&
|
|
247712
|
-
!normalizedFileName.includes('/node_modules/'));
|
|
247713
|
-
}
|
|
247714
247735
|
function resolveModule(program, containingFile, moduleSpecifier) {
|
|
247715
|
-
|
|
247716
|
-
|
|
247717
|
-
|
|
247718
|
-
|
|
247736
|
+
// Prefer the program's own resolution cache (already populated during compilation)
|
|
247737
|
+
// over running a fresh resolution, which requires file system access per unique
|
|
247738
|
+
// (directory, module) pair and dominates lint time on cold starts.
|
|
247739
|
+
const programCache = getProgramResolutionCache(program);
|
|
247740
|
+
if (programCache) {
|
|
247741
|
+
const fromCache = ts.resolveModuleNameFromCache(moduleSpecifier, containingFile, programCache);
|
|
247742
|
+
if (fromCache !== undefined) {
|
|
247743
|
+
return fromCache.resolvedModule ?? null;
|
|
247744
|
+
}
|
|
247745
|
+
}
|
|
247746
|
+
const { compilerHost, resolutionCache } = getFallbackResolution(program);
|
|
247747
|
+
return (ts.resolveModuleName(moduleSpecifier, containingFile, program.getCompilerOptions(), compilerHost, resolutionCache).resolvedModule ?? null);
|
|
247719
247748
|
}
|
|
247720
247749
|
function resolveModuleFileName(program, containingFile, moduleSpecifier) {
|
|
247721
247750
|
const resolved = resolveModule(program, containingFile, moduleSpecifier);
|
|
@@ -247802,7 +247831,11 @@ function buildDependenciesByFileName(program, canonicalFileName) {
|
|
|
247802
247831
|
if (!projectFileNames.has(targetFileName)) {
|
|
247803
247832
|
continue;
|
|
247804
247833
|
}
|
|
247805
|
-
edges.push({
|
|
247834
|
+
edges.push({
|
|
247835
|
+
isImport: ts.isImportDeclaration(statement),
|
|
247836
|
+
moduleSpecifier,
|
|
247837
|
+
targetFileName,
|
|
247838
|
+
});
|
|
247806
247839
|
}
|
|
247807
247840
|
dependenciesByFileName.set(fileName, edges);
|
|
247808
247841
|
}
|
|
@@ -247877,6 +247910,32 @@ function collectSelfCycles(dependenciesByFileName) {
|
|
|
247877
247910
|
}
|
|
247878
247911
|
return selfCycleFileNames;
|
|
247879
247912
|
}
|
|
247913
|
+
function buildSccHasImportEdge(dependenciesByFileName, componentIdByFileName) {
|
|
247914
|
+
const result = new Map();
|
|
247915
|
+
for (const [fileName, edges] of dependenciesByFileName) {
|
|
247916
|
+
const sourceComponentId = componentIdByFileName.get(fileName);
|
|
247917
|
+
if (sourceComponentId === undefined || result.get(sourceComponentId) === true) {
|
|
247918
|
+
continue;
|
|
247919
|
+
}
|
|
247920
|
+
for (const edge of edges) {
|
|
247921
|
+
if (edge.isImport &&
|
|
247922
|
+
componentIdByFileName.get(edge.targetFileName) === sourceComponentId) {
|
|
247923
|
+
result.set(sourceComponentId, true);
|
|
247924
|
+
break;
|
|
247925
|
+
}
|
|
247926
|
+
}
|
|
247927
|
+
}
|
|
247928
|
+
return result;
|
|
247929
|
+
}
|
|
247930
|
+
function buildBarrelFileNames(dependenciesByFileName) {
|
|
247931
|
+
const result = new Set();
|
|
247932
|
+
for (const [fileName, edges] of dependenciesByFileName) {
|
|
247933
|
+
if (edges.some((edge) => !edge.isImport)) {
|
|
247934
|
+
result.add(fileName);
|
|
247935
|
+
}
|
|
247936
|
+
}
|
|
247937
|
+
return result;
|
|
247938
|
+
}
|
|
247880
247939
|
function getImportGraph(program) {
|
|
247881
247940
|
const cached = importGraphCacheByProgram.get(program);
|
|
247882
247941
|
if (cached) {
|
|
@@ -247886,10 +247945,12 @@ function getImportGraph(program) {
|
|
|
247886
247945
|
const { dependenciesByFileName, displayFileNameByFileName } = buildDependenciesByFileName(program, canonicalFileName);
|
|
247887
247946
|
const { componentIdByFileName, componentSizeById } = findStronglyConnectedComponents(dependenciesByFileName);
|
|
247888
247947
|
const cache = {
|
|
247948
|
+
barrelFileNames: buildBarrelFileNames(dependenciesByFileName),
|
|
247889
247949
|
componentIdByFileName,
|
|
247890
247950
|
componentSizeById,
|
|
247891
247951
|
dependenciesByFileName,
|
|
247892
247952
|
displayFileNameByFileName,
|
|
247953
|
+
sccHasImportEdgeById: buildSccHasImportEdge(dependenciesByFileName, componentIdByFileName),
|
|
247893
247954
|
selfCycleFileNames: collectSelfCycles(dependenciesByFileName),
|
|
247894
247955
|
};
|
|
247895
247956
|
importGraphCacheByProgram.set(program, cache);
|
|
@@ -248103,6 +248164,34 @@ function getExportSpecifierName(name) {
|
|
|
248103
248164
|
function hasNamedValueExport(exportNames, exportedName) {
|
|
248104
248165
|
return exportedName !== 'default' && (exportNames?.has(exportedName) ?? false);
|
|
248105
248166
|
}
|
|
248167
|
+
// Angular resolves the reference lazily (at instantiation, not at module load time)
|
|
248168
|
+
// in all of these contexts, so a cycle through them is safe at the ES module level.
|
|
248169
|
+
function isInAngularSafeContext(identifier) {
|
|
248170
|
+
// TSESTree types parent as Node (non-optional), but the root node's parent is
|
|
248171
|
+
// null at runtime. Widening to include null/undefined lets while(current) serve
|
|
248172
|
+
// as the exit condition when traversal reaches the top of the tree.
|
|
248173
|
+
let current = identifier.parent;
|
|
248174
|
+
while (current) {
|
|
248175
|
+
// Lazy evaluation: body runs only when the function/arrow is called.
|
|
248176
|
+
if (current.type === dist$3.AST_NODE_TYPES.ArrowFunctionExpression ||
|
|
248177
|
+
current.type === dist$3.AST_NODE_TYPES.FunctionExpression ||
|
|
248178
|
+
current.type === dist$3.AST_NODE_TYPES.FunctionDeclaration) {
|
|
248179
|
+
return true;
|
|
248180
|
+
}
|
|
248181
|
+
// Angular decorator metadata (@Component, @Directive, etc.) is processed
|
|
248182
|
+
// after all modules in the cycle have finished loading.
|
|
248183
|
+
if (current.type === dist$3.AST_NODE_TYPES.Decorator) {
|
|
248184
|
+
return true;
|
|
248185
|
+
}
|
|
248186
|
+
// Non-static class field initializers run at instantiation time, not at
|
|
248187
|
+
// module load time, so they do not create a load-time cycle edge.
|
|
248188
|
+
if (current.type === dist$3.AST_NODE_TYPES.PropertyDefinition && !current.static) {
|
|
248189
|
+
return true;
|
|
248190
|
+
}
|
|
248191
|
+
current = current.parent;
|
|
248192
|
+
}
|
|
248193
|
+
return false;
|
|
248194
|
+
}
|
|
248106
248195
|
function isImportUsedOnlyAsAngularDiFirstArg(node, sourceCode) {
|
|
248107
248196
|
const valueSpecifiers = node.specifiers.filter((specifier) => {
|
|
248108
248197
|
if (specifier.type === dist$3.AST_NODE_TYPES.ImportDefaultSpecifier ||
|
|
@@ -248114,6 +248203,10 @@ function isImportUsedOnlyAsAngularDiFirstArg(node, sourceCode) {
|
|
|
248114
248203
|
if (valueSpecifiers.length === 0) {
|
|
248115
248204
|
return false;
|
|
248116
248205
|
}
|
|
248206
|
+
// True if at least one reference is a genuine DI call or lives in a lazy/decorator
|
|
248207
|
+
// context. Pure type-only references don't count: an import used only as a type
|
|
248208
|
+
// should use `import type` and is not considered safe from a cycle perspective.
|
|
248209
|
+
let hasSafeRuntimeUsage = false;
|
|
248117
248210
|
for (const specifier of valueSpecifiers) {
|
|
248118
248211
|
const [variable] = sourceCode.getDeclaredVariables(specifier);
|
|
248119
248212
|
if (!variable || variable.references.length === 0) {
|
|
@@ -248122,6 +248215,17 @@ function isImportUsedOnlyAsAngularDiFirstArg(node, sourceCode) {
|
|
|
248122
248215
|
for (const ref of variable.references) {
|
|
248123
248216
|
const { identifier } = ref;
|
|
248124
248217
|
const parent = identifier.parent;
|
|
248218
|
+
// Type-only references (e.g., param: Type<T>) don't create runtime
|
|
248219
|
+
// dependencies. Skip without marking hasSafeRuntimeUsage — an import
|
|
248220
|
+
// that is exclusively used as a type should use `import type` instead.
|
|
248221
|
+
if (parent.type === dist$3.AST_NODE_TYPES.TSTypeReference) {
|
|
248222
|
+
continue;
|
|
248223
|
+
}
|
|
248224
|
+
// References inside lazy/decorator contexts don't create load-time edges.
|
|
248225
|
+
if (isInAngularSafeContext(identifier)) {
|
|
248226
|
+
hasSafeRuntimeUsage = true;
|
|
248227
|
+
continue;
|
|
248228
|
+
}
|
|
248125
248229
|
const callee = parent.type === dist$3.AST_NODE_TYPES.CallExpression ? parent.callee : null;
|
|
248126
248230
|
const isDirectCall = callee?.type === dist$3.AST_NODE_TYPES.Identifier &&
|
|
248127
248231
|
ANGULAR_DI_FIRST_ARG_FUNCTIONS.has(callee.name);
|
|
@@ -248136,9 +248240,10 @@ function isImportUsedOnlyAsAngularDiFirstArg(node, sourceCode) {
|
|
|
248136
248240
|
parent.arguments[0] !== identifier) {
|
|
248137
248241
|
return false;
|
|
248138
248242
|
}
|
|
248243
|
+
hasSafeRuntimeUsage = true;
|
|
248139
248244
|
}
|
|
248140
248245
|
}
|
|
248141
|
-
return
|
|
248246
|
+
return hasSafeRuntimeUsage;
|
|
248142
248247
|
}
|
|
248143
248248
|
const rule$K = createRule({
|
|
248144
248249
|
create(context) {
|
|
@@ -248165,18 +248270,111 @@ const rule$K = createRule({
|
|
|
248165
248270
|
}
|
|
248166
248271
|
const graph = getImportGraph(tsProgram);
|
|
248167
248272
|
const targetFileName = findCyclicTargetFileName(graph, currentFileName, moduleSpecifier);
|
|
248168
|
-
if (!targetFileName
|
|
248169
|
-
(node.type === dist$3.AST_NODE_TYPES.ImportDeclaration &&
|
|
248170
|
-
isImportUsedOnlyAsAngularDiFirstArg(node, sourceCode))) {
|
|
248273
|
+
if (!targetFileName) {
|
|
248171
248274
|
return;
|
|
248172
248275
|
}
|
|
248173
|
-
context.
|
|
248174
|
-
|
|
248175
|
-
|
|
248176
|
-
|
|
248177
|
-
|
|
248178
|
-
|
|
248179
|
-
|
|
248276
|
+
const cyclePath = formatCyclePath(graph, currentFileName, targetFileName, context.cwd);
|
|
248277
|
+
if (node.type === dist$3.AST_NODE_TYPES.ImportDeclaration) {
|
|
248278
|
+
// Compute the redirect replacement eagerly so we can decide whether
|
|
248279
|
+
// to suppress. If a redirect to the direct source file is possible,
|
|
248280
|
+
// always report (the fix breaks the cycle). Otherwise, suppress when
|
|
248281
|
+
// all usages are Angular-DI-safe (inject, class fields, etc.).
|
|
248282
|
+
const replacement = computeCycleBreakingReplacement(node);
|
|
248283
|
+
if (!replacement &&
|
|
248284
|
+
isImportUsedOnlyAsAngularDiFirstArg(node, sourceCode)) {
|
|
248285
|
+
return;
|
|
248286
|
+
}
|
|
248287
|
+
context.report({
|
|
248288
|
+
data: { cyclePath },
|
|
248289
|
+
fix: replacement
|
|
248290
|
+
? (fixer) => [fixer.replaceText(node, replacement)]
|
|
248291
|
+
: undefined,
|
|
248292
|
+
messageId: 'importCycle',
|
|
248293
|
+
node: sourceNode,
|
|
248294
|
+
});
|
|
248295
|
+
}
|
|
248296
|
+
else {
|
|
248297
|
+
// For re-export nodes (export * from / export {x} from), suppress the
|
|
248298
|
+
// error when the same SCC already contains an ImportDeclaration edge.
|
|
248299
|
+
// That ImportDeclaration will be reported (and fixed) directly, so
|
|
248300
|
+
// reporting the barrel re-export would create duplicate, unfixable noise.
|
|
248301
|
+
const componentId = graph.componentIdByFileName.get(currentFileName);
|
|
248302
|
+
if (componentId !== undefined &&
|
|
248303
|
+
graph.sccHasImportEdgeById.get(componentId) === true) {
|
|
248304
|
+
return;
|
|
248305
|
+
}
|
|
248306
|
+
context.report({
|
|
248307
|
+
data: { cyclePath },
|
|
248308
|
+
messageId: 'importCycle',
|
|
248309
|
+
node: sourceNode,
|
|
248310
|
+
});
|
|
248311
|
+
}
|
|
248312
|
+
}
|
|
248313
|
+
function computeCycleBreakingReplacement(node) {
|
|
248314
|
+
// Only named imports can be safely redirected to their source file
|
|
248315
|
+
if (node.specifiers.some((s) => s.type !== dist$3.AST_NODE_TYPES.ImportSpecifier)) {
|
|
248316
|
+
return null;
|
|
248317
|
+
}
|
|
248318
|
+
const barrelFileName = resolveModuleFileName(tsProgram, context.filename, node.source.value);
|
|
248319
|
+
const canonicalBarrelFileName = barrelFileName
|
|
248320
|
+
? canonicalFileName(barrelFileName)
|
|
248321
|
+
: null;
|
|
248322
|
+
// Not a barrel (has no re-export edges) — symbols are defined locally,
|
|
248323
|
+
// so there is no shorter direct-source path to redirect to.
|
|
248324
|
+
if (!canonicalBarrelFileName ||
|
|
248325
|
+
!getImportGraph(tsProgram).barrelFileNames.has(canonicalBarrelFileName)) {
|
|
248326
|
+
return null;
|
|
248327
|
+
}
|
|
248328
|
+
const specifiersBySourceFile = new Map();
|
|
248329
|
+
for (const specifier of node.specifiers) {
|
|
248330
|
+
if (specifier.type !== dist$3.AST_NODE_TYPES.ImportSpecifier) {
|
|
248331
|
+
return null;
|
|
248332
|
+
}
|
|
248333
|
+
const tsSpecifier = esTreeNodeToTSNodeMap.get(specifier);
|
|
248334
|
+
if (!ts.isImportSpecifier(tsSpecifier)) {
|
|
248335
|
+
return null;
|
|
248336
|
+
}
|
|
248337
|
+
const localSymbol = checker.getSymbolAtLocation(tsSpecifier.name);
|
|
248338
|
+
if (!localSymbol) {
|
|
248339
|
+
return null;
|
|
248340
|
+
}
|
|
248341
|
+
const originalSymbol = getAliasedSymbolIfNeeded(checker, localSymbol);
|
|
248342
|
+
const { declarations } = originalSymbol;
|
|
248343
|
+
const firstDeclaration = declarations?.[0];
|
|
248344
|
+
if (!firstDeclaration) {
|
|
248345
|
+
return null;
|
|
248346
|
+
}
|
|
248347
|
+
const sourceFile = firstDeclaration.getSourceFile();
|
|
248348
|
+
if (!isProjectCodeFile(sourceFile)) {
|
|
248349
|
+
return null;
|
|
248350
|
+
}
|
|
248351
|
+
const sourceFilePath = sourceFile.fileName;
|
|
248352
|
+
// Symbol is defined directly in the barrel — no shorter path exists
|
|
248353
|
+
if (canonicalBarrelFileName === canonicalFileName(sourceFilePath)) {
|
|
248354
|
+
return null;
|
|
248355
|
+
}
|
|
248356
|
+
const importedName = tsSpecifier.propertyName?.text ?? tsSpecifier.name.text;
|
|
248357
|
+
const localName = tsSpecifier.name.text;
|
|
248358
|
+
const typePrefix = specifier.importKind === 'type' ? 'type ' : '';
|
|
248359
|
+
const specText = importedName === localName
|
|
248360
|
+
? `${typePrefix}${importedName}`
|
|
248361
|
+
: `${typePrefix}${importedName} as ${localName}`;
|
|
248362
|
+
const group = specifiersBySourceFile.get(sourceFilePath) ?? [];
|
|
248363
|
+
group.push(specText);
|
|
248364
|
+
specifiersBySourceFile.set(sourceFilePath, group);
|
|
248365
|
+
}
|
|
248366
|
+
if (specifiersBySourceFile.size === 0) {
|
|
248367
|
+
return null;
|
|
248368
|
+
}
|
|
248369
|
+
const semi = sourceCode.getText(node).endsWith(';') ? ';' : '';
|
|
248370
|
+
const quote = node.source.raw[0] ?? "'";
|
|
248371
|
+
const importPrefix = node.importKind === 'type' ? 'import type' : 'import';
|
|
248372
|
+
const newImports = [];
|
|
248373
|
+
for (const [sourceFilePath, names] of specifiersBySourceFile) {
|
|
248374
|
+
const relPath = computeRelativeImportPath(context.filename, sourceFilePath);
|
|
248375
|
+
newImports.push(`${importPrefix} {${names.join(', ')}} from ${quote}${relPath}${quote}${semi}`);
|
|
248376
|
+
}
|
|
248377
|
+
return newImports.join('\n');
|
|
248180
248378
|
}
|
|
248181
248379
|
function checkDefaultImport(node) {
|
|
248182
248380
|
if ((!checkDefaultImports && !checkNamedAsDefault) ||
|
|
@@ -250700,6 +250898,19 @@ function isNullableCallType(call, checker, nodeMap) {
|
|
|
250700
250898
|
return false;
|
|
250701
250899
|
}
|
|
250702
250900
|
}
|
|
250901
|
+
function getTargetNode(call) {
|
|
250902
|
+
const { parent } = call;
|
|
250903
|
+
if (parent.type === dist$3.AST_NODE_TYPES.TSAsExpression) {
|
|
250904
|
+
return parent;
|
|
250905
|
+
}
|
|
250906
|
+
if (parent.type === dist$3.AST_NODE_TYPES.UnaryExpression &&
|
|
250907
|
+
parent.operator === '!' &&
|
|
250908
|
+
parent.parent.type === dist$3.AST_NODE_TYPES.UnaryExpression &&
|
|
250909
|
+
parent.parent.operator === '!') {
|
|
250910
|
+
return parent.parent;
|
|
250911
|
+
}
|
|
250912
|
+
return call;
|
|
250913
|
+
}
|
|
250703
250914
|
function getCalleeName(node) {
|
|
250704
250915
|
const { callee } = node;
|
|
250705
250916
|
if (callee.type === dist$3.AST_NODE_TYPES.MemberExpression &&
|
|
@@ -250795,11 +251006,7 @@ const rule$r = createRule({
|
|
|
250795
251006
|
fixer.insertTextBefore(parentStatement, `const ${varName} = ${callText};\n\n${indent}`),
|
|
250796
251007
|
];
|
|
250797
251008
|
for (const call of calls) {
|
|
250798
|
-
|
|
250799
|
-
const target = parent.type === dist$3.AST_NODE_TYPES.TSAsExpression
|
|
250800
|
-
? parent
|
|
250801
|
-
: call;
|
|
250802
|
-
fixes.push(fixer.replaceText(target, varName));
|
|
251009
|
+
fixes.push(fixer.replaceText(getTargetNode(call), varName));
|
|
250803
251010
|
}
|
|
250804
251011
|
return fixes;
|
|
250805
251012
|
}
|
|
@@ -250812,12 +251019,7 @@ const rule$r = createRule({
|
|
|
250812
251019
|
const bodyText = sourceCode.getText(arrowBody);
|
|
250813
251020
|
const bodyStart = arrowBody.range[0];
|
|
250814
251021
|
const targets = calls
|
|
250815
|
-
.map(
|
|
250816
|
-
const { parent } = call;
|
|
250817
|
-
return parent.type === dist$3.AST_NODE_TYPES.TSAsExpression
|
|
250818
|
-
? parent
|
|
250819
|
-
: call;
|
|
250820
|
-
})
|
|
251022
|
+
.map(getTargetNode)
|
|
250821
251023
|
.sort((a, b) => a.range[0] - b.range[0]);
|
|
250822
251024
|
let replacedBody = '';
|
|
250823
251025
|
let lastIndex = 0;
|
|
@@ -250829,7 +251031,13 @@ const rule$r = createRule({
|
|
|
250829
251031
|
}
|
|
250830
251032
|
replacedBody += bodyText.slice(lastIndex);
|
|
250831
251033
|
const newBody = `{\n${innerIndent}const ${varName} = ${callText};\n\n${innerIndent}return ${replacedBody};\n${outerIndent}}`;
|
|
250832
|
-
|
|
251034
|
+
const bodyRangeStart = arrowBody.range[0];
|
|
251035
|
+
const textBeforeBody = sourceCode.text.slice(0, bodyRangeStart);
|
|
251036
|
+
const whitespaceBeforeBody = /\s*$/.exec(textBeforeBody)?.[0] ?? '';
|
|
251037
|
+
const replaceFrom = bodyRangeStart - whitespaceBeforeBody.length;
|
|
251038
|
+
return [
|
|
251039
|
+
fixer.replaceTextRange([replaceFrom, arrowBody.range[1]], ` ${newBody}`),
|
|
251040
|
+
];
|
|
250833
251041
|
},
|
|
250834
251042
|
messageId: 'noRepeatedSignalInConditional',
|
|
250835
251043
|
node: firstCall,
|