@taiga-ui/eslint-plugin-experience-next 0.498.0 → 0.500.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 CHANGED
@@ -875,6 +875,7 @@ var recommended = defineConfig([
875
875
  'func-style': ['error', 'declaration', { allowArrowFunctions: true }],
876
876
  'guard-for-in': 'error',
877
877
  'import/consistent-type-specifier-style': ['error', 'prefer-inline'],
878
+ 'import/default': 'off',
878
879
  'import/enforce-node-protocol-usage': ['error', 'always'],
879
880
  'import/export': 'off',
880
881
  'import/first': 'error',
@@ -885,7 +886,7 @@ var recommended = defineConfig([
885
886
  'import/no-duplicates': ['error', { 'prefer-inline': true }],
886
887
  'import/no-extraneous-dependencies': 'off',
887
888
  'import/no-mutable-exports': 'error',
888
- 'import/no-named-as-default': 'error',
889
+ 'import/no-named-as-default': 'off',
889
890
  'import/no-self-import': 'error',
890
891
  'import/no-unresolved': 'off',
891
892
  'import/no-useless-path-segments': ['error', { noUselessIndex: true }],
@@ -1188,6 +1189,7 @@ var recommended = defineConfig([
1188
1189
  },
1189
1190
  ],
1190
1191
  '@taiga-ui/experience-next/host-attributes-sort': 'error',
1192
+ '@taiga-ui/experience-next/import-integrity': 'error',
1191
1193
  '@taiga-ui/experience-next/injection-token-description': 'error',
1192
1194
  '@taiga-ui/experience-next/no-commonjs-import-patterns': 'error',
1193
1195
  '@taiga-ui/experience-next/no-deep-imports': [
@@ -1203,6 +1205,7 @@ var recommended = defineConfig([
1203
1205
  '@taiga-ui/experience-next/no-import-assertions': 'error',
1204
1206
  '@taiga-ui/experience-next/no-infinite-loop': 'error',
1205
1207
  '@taiga-ui/experience-next/no-redundant-type-annotation': 'error',
1208
+ '@taiga-ui/experience-next/no-repeated-signal-in-conditional': 'error',
1206
1209
  '@taiga-ui/experience-next/no-side-effects-in-computed': 'error',
1207
1210
  '@taiga-ui/experience-next/no-signal-reads-after-await-in-reactive-context': 'error',
1208
1211
  '@taiga-ui/experience-next/no-untracked-outside-reactive-context': 'error',
@@ -1215,6 +1218,7 @@ var recommended = defineConfig([
1215
1218
  '@taiga-ui/experience-next/prefer-untracked-signal-getter': 'error',
1216
1219
  '@taiga-ui/experience-next/short-tui-imports': 'error',
1217
1220
  '@taiga-ui/experience-next/single-line-class-property-spacing': 'error',
1221
+ '@taiga-ui/experience-next/single-line-variable-spacing': 'error',
1218
1222
  '@taiga-ui/experience-next/standalone-imports-sort': [
1219
1223
  'error',
1220
1224
  { decorators: ['Component', 'Directive', 'NgModule', 'Pipe'] },
@@ -46217,7 +46221,7 @@ function buildMultilineStartTag(node, sourceText) {
46217
46221
  closing,
46218
46222
  ].join('\n');
46219
46223
  }
46220
- const rule$M = createRule({
46224
+ const rule$P = createRule({
46221
46225
  name: 'attrs-newline',
46222
46226
  rule: {
46223
46227
  create(context) {
@@ -46364,7 +46368,7 @@ const config$5 = {
46364
46368
  function getCorrectOrderRelative(correct, current) {
46365
46369
  return correct.filter((item) => current.includes(item));
46366
46370
  }
46367
- const rule$L = createRule({
46371
+ const rule$O = createRule({
46368
46372
  name: 'decorator-key-sort',
46369
46373
  rule: config$5,
46370
46374
  });
@@ -46428,7 +46432,7 @@ function getNodeLabel(node) {
46428
46432
  }
46429
46433
  return 'text';
46430
46434
  }
46431
- const rule$K = createRule({
46435
+ const rule$N = createRule({
46432
46436
  name: 'element-newline',
46433
46437
  rule: {
46434
46438
  create(context) {
@@ -46659,7 +46663,7 @@ const PRESETS = {
46659
46663
  $VUE: ['$CLASS', '$ID', '$VUE_ATTRIBUTE'],
46660
46664
  $VUE_ATTRIBUTE: /^v-/,
46661
46665
  };
46662
- const rule$J = createRule({
46666
+ const rule$M = createRule({
46663
46667
  create(context, [options]) {
46664
46668
  const sourceCode = context.sourceCode;
46665
46669
  const settings = {
@@ -46992,317 +46996,11 @@ const config$4 = {
46992
46996
  type: 'suggestion',
46993
46997
  },
46994
46998
  };
46995
- const rule$I = createRule({
46999
+ const rule$L = createRule({
46996
47000
  name: 'html-logical-properties',
46997
47001
  rule: config$4,
46998
47002
  });
46999
47003
 
47000
- const MESSAGE_ID$e = 'invalid-injection-token-description';
47001
- const ERROR_MESSAGE$3 = "InjectionToken's description should contain token's name";
47002
- const NG_DEV_MODE = 'ngDevMode';
47003
- function getVariableName(node) {
47004
- if (node.parent.type !== dist$2.AST_NODE_TYPES.VariableDeclarator) {
47005
- return undefined;
47006
- }
47007
- const { id } = node.parent;
47008
- return id.type === dist$2.AST_NODE_TYPES.Identifier ? id.name : undefined;
47009
- }
47010
- function isStringLike(node) {
47011
- return isStringLiteral(node) || node.type === dist$2.AST_NODE_TYPES.TemplateLiteral;
47012
- }
47013
- function getStringValue(node) {
47014
- if (isStringLiteral(node)) {
47015
- return node.value;
47016
- }
47017
- return node.quasis[0]?.value.raw || '';
47018
- }
47019
- function isEmptyString(node) {
47020
- return (isEmptyStaticString(node) &&
47021
- (!('expressions' in node) || node.expressions.length === 0));
47022
- }
47023
- function isNgDevModeConditional(node) {
47024
- return (node.type === dist$2.AST_NODE_TYPES.ConditionalExpression &&
47025
- node.test.type === dist$2.AST_NODE_TYPES.Identifier &&
47026
- node.test.name === NG_DEV_MODE &&
47027
- isStringLike(node.consequent) &&
47028
- isStringLike(node.alternate) &&
47029
- isEmptyString(node.alternate));
47030
- }
47031
- function getDescriptionValue(node) {
47032
- if (isStringLike(node)) {
47033
- return getStringValue(node);
47034
- }
47035
- if (isNgDevModeConditional(node)) {
47036
- return getStringValue(node.consequent);
47037
- }
47038
- return undefined;
47039
- }
47040
- function getDescriptionNode(node) {
47041
- if (isStringLike(node)) {
47042
- return node;
47043
- }
47044
- return isNgDevModeConditional(node) ? node.consequent : undefined;
47045
- }
47046
- function prependTokenName(text, name) {
47047
- return `${text.slice(0, 1)}[${name}]: ${text.slice(1)}`;
47048
- }
47049
- function isNgDevModeVisible(sourceCode, node) {
47050
- for (let scope = sourceCode.getScope(node); scope !== null; scope = scope.upper) {
47051
- if (scope.variables.some((variable) => variable.name === NG_DEV_MODE)) {
47052
- return true;
47053
- }
47054
- }
47055
- return false;
47056
- }
47057
- function getNgDevModeDeclarationFix(program, fixer) {
47058
- const lastImport = [...program.body]
47059
- .reverse()
47060
- .find((statement) => statement.type === dist$2.AST_NODE_TYPES.ImportDeclaration);
47061
- if (lastImport) {
47062
- return fixer.insertTextAfter(lastImport, '\n\ndeclare const ngDevMode: boolean;');
47063
- }
47064
- const [firstStatement] = program.body;
47065
- if (firstStatement) {
47066
- return fixer.insertTextBefore(firstStatement, 'declare const ngDevMode: boolean;\n\n');
47067
- }
47068
- return fixer.insertTextBeforeRange([0, 0], 'declare const ngDevMode: boolean;\n');
47069
- }
47070
- const rule$H = createRule({
47071
- create(context) {
47072
- const { sourceCode } = context;
47073
- const program = sourceCode.ast;
47074
- let shouldAddNgDevModeDeclaration = true;
47075
- return {
47076
- 'NewExpression[callee.name="InjectionToken"]'(node) {
47077
- const [description] = node.arguments;
47078
- if (!description || description.type === dist$2.AST_NODE_TYPES.SpreadElement) {
47079
- return;
47080
- }
47081
- const name = getVariableName(node);
47082
- const token = getDescriptionValue(description);
47083
- const fixedDescription = getDescriptionNode(description);
47084
- const report = name && token && !token.includes(name);
47085
- if (report && fixedDescription) {
47086
- context.report({
47087
- fix: (fixer) => {
47088
- const isNgDevModeGuarded = isNgDevModeConditional(description);
47089
- const fixes = [
47090
- fixer.replaceText(isNgDevModeGuarded ? fixedDescription : description, isNgDevModeGuarded
47091
- ? prependTokenName(sourceCode.getText(fixedDescription), name)
47092
- : `${NG_DEV_MODE} ? ${prependTokenName(sourceCode.getText(fixedDescription), name)} : ''`),
47093
- ];
47094
- if (!isNgDevModeGuarded &&
47095
- shouldAddNgDevModeDeclaration &&
47096
- !isNgDevModeVisible(sourceCode, description)) {
47097
- shouldAddNgDevModeDeclaration = false;
47098
- fixes.unshift(getNgDevModeDeclarationFix(program, fixer));
47099
- }
47100
- return fixes;
47101
- },
47102
- messageId: MESSAGE_ID$e,
47103
- node: description,
47104
- });
47105
- }
47106
- },
47107
- };
47108
- },
47109
- meta: {
47110
- docs: { description: ERROR_MESSAGE$3 },
47111
- fixable: 'code',
47112
- messages: { [MESSAGE_ID$e]: ERROR_MESSAGE$3 },
47113
- schema: [],
47114
- type: 'problem',
47115
- },
47116
- name: 'injection-token-description',
47117
- });
47118
-
47119
- function getResolvedVariable(sourceCode, node) {
47120
- const scope = sourceCode.getScope(node);
47121
- const reference = scope.references.find((item) => item.identifier === node);
47122
- return reference?.resolved ?? null;
47123
- }
47124
- const rule$G = createRule({
47125
- create(context) {
47126
- const { sourceCode } = context;
47127
- const namespaceImports = new Map();
47128
- const markNamespaceImportAsUsedLikeValue = (identifier) => {
47129
- const usage = namespaceImports.get(identifier.name);
47130
- if (!usage ||
47131
- usage.usedLikeValue ||
47132
- getResolvedVariable(sourceCode, identifier) !== usage.variable) {
47133
- return;
47134
- }
47135
- usage.usedLikeValue = true;
47136
- };
47137
- return {
47138
- 'CallExpression > Identifier.callee'(node) {
47139
- markNamespaceImportAsUsedLikeValue(node);
47140
- },
47141
- ImportDeclaration(node) {
47142
- const namespaceImport = node.specifiers.find((specifier) => specifier.type === dist$3.AST_NODE_TYPES.ImportNamespaceSpecifier);
47143
- if (!namespaceImport) {
47144
- return;
47145
- }
47146
- const [variable] = sourceCode.getDeclaredVariables(namespaceImport);
47147
- if (!variable) {
47148
- return;
47149
- }
47150
- namespaceImports.set(namespaceImport.local.name, {
47151
- node: namespaceImport,
47152
- usedLikeValue: false,
47153
- variable,
47154
- });
47155
- },
47156
- 'NewExpression > Identifier.callee'(node) {
47157
- markNamespaceImportAsUsedLikeValue(node);
47158
- },
47159
- 'Program:exit'() {
47160
- for (const usage of namespaceImports.values()) {
47161
- if (!usage.usedLikeValue) {
47162
- continue;
47163
- }
47164
- context.report({
47165
- data: { name: usage.node.local.name },
47166
- messageId: 'avoidCallableNamespaceImport',
47167
- node: usage.node,
47168
- });
47169
- }
47170
- },
47171
- 'TaggedTemplateExpression > Identifier.tag'(node) {
47172
- markNamespaceImportAsUsedLikeValue(node);
47173
- },
47174
- TSImportEqualsDeclaration(node) {
47175
- if (node.moduleReference.type !== dist$3.AST_NODE_TYPES.TSExternalModuleReference) {
47176
- return;
47177
- }
47178
- context.report({
47179
- data: { name: node.id.name },
47180
- messageId: 'avoidImportEquals',
47181
- node,
47182
- });
47183
- },
47184
- };
47185
- },
47186
- meta: {
47187
- docs: {
47188
- description: 'Disallow legacy CommonJS interop import patterns such as `import = require(...)` and namespace imports used like callable values.',
47189
- },
47190
- messages: {
47191
- avoidCallableNamespaceImport: 'Namespace import "{{name}}" is used like a value instead of a namespace. This is a brittle interop pattern and often should become a default import.',
47192
- avoidImportEquals: '`import {{name}} = require(...)` is a legacy CommonJS import pattern.',
47193
- },
47194
- schema: [],
47195
- type: 'problem',
47196
- },
47197
- name: 'no-commonjs-import-patterns',
47198
- });
47199
-
47200
- const MESSAGE_ID$d = 'no-deep-imports';
47201
- const ERROR_MESSAGE$2 = 'Deep imports of Taiga UI packages are prohibited';
47202
- const CODE_EXTENSIONS = new Set([
47203
- '.cjs',
47204
- '.cts',
47205
- '.js',
47206
- '.jsx',
47207
- '.mjs',
47208
- '.mts',
47209
- '.ts',
47210
- '.tsx',
47211
- ]);
47212
- const DEFAULT_OPTIONS = {
47213
- currentProject: '',
47214
- deepImport: String.raw `(?<=^@taiga-ui/[\w-]+)(/.+)$`,
47215
- ignoreImports: [],
47216
- importDeclaration: '^@taiga-ui*',
47217
- projectName: String.raw `(?<=^@taiga-ui/)([-\w]+)`,
47218
- };
47219
- const rule$F = createRule({
47220
- create(context) {
47221
- const { currentProject, deepImport, ignoreImports, importDeclaration, projectName, } = { ...DEFAULT_OPTIONS, ...context.options[0] };
47222
- const hasNonCodeExtension = (source) => {
47223
- if (!source) {
47224
- return false;
47225
- }
47226
- const cleanSource = source.split(/[?#]/, 1)[0] ?? '';
47227
- const extension = path.posix.extname(cleanSource).toLowerCase();
47228
- return !!extension && !CODE_EXTENSIONS.has(extension);
47229
- };
47230
- const isDeepImport = (source) => !!source && new RegExp(deepImport, 'g').test(source);
47231
- const isSideEffectImport = (node) => node.specifiers.length === 0;
47232
- const isInsideTheSameEntryPoint = (source) => {
47233
- const filePath = path
47234
- .relative(context.cwd, context.filename)
47235
- .replaceAll(/\\+/g, '/');
47236
- const [currentFileProjectName] = (currentProject && new RegExp(currentProject, 'g').exec(filePath)) ?? [];
47237
- const [importSourceProjectName] = source?.match(new RegExp(projectName, 'g')) ?? [];
47238
- return Boolean(currentFileProjectName &&
47239
- importSourceProjectName &&
47240
- currentFileProjectName === importSourceProjectName);
47241
- };
47242
- const shouldIgnore = (source) => !!source && ignoreImports.some((p) => new RegExp(p, 'g').test(source));
47243
- return {
47244
- [`ImportDeclaration[source.value=/${importDeclaration}/]`](node) {
47245
- if (!node || isSideEffectImport(node)) {
47246
- return;
47247
- }
47248
- const importSource = node.source.value;
47249
- if (!importSource ||
47250
- !isDeepImport(importSource) ||
47251
- isInsideTheSameEntryPoint(importSource) ||
47252
- shouldIgnore(importSource) ||
47253
- hasNonCodeExtension(importSource)) {
47254
- return;
47255
- }
47256
- context.report({
47257
- fix: (fixer) => {
47258
- const [start, end] = node.source.range;
47259
- return fixer.replaceTextRange([start + 1, end - 1], importSource.replaceAll(new RegExp(deepImport, 'g'), ''));
47260
- },
47261
- messageId: MESSAGE_ID$d,
47262
- node: node.source,
47263
- });
47264
- },
47265
- };
47266
- },
47267
- meta: {
47268
- defaultOptions: [DEFAULT_OPTIONS],
47269
- docs: { description: ERROR_MESSAGE$2 },
47270
- fixable: 'code',
47271
- messages: { [MESSAGE_ID$d]: ERROR_MESSAGE$2 },
47272
- schema: [
47273
- {
47274
- additionalProperties: false,
47275
- properties: {
47276
- currentProject: {
47277
- description: 'RegExp string to pick out current project name of processed file',
47278
- type: 'string',
47279
- },
47280
- deepImport: {
47281
- description: 'RegExp string to pick out deep import part',
47282
- type: 'string',
47283
- },
47284
- ignoreImports: {
47285
- description: 'RegExp string to exclude import declarations which is selected by importDeclaration-option',
47286
- items: { type: 'string' },
47287
- type: 'array',
47288
- },
47289
- importDeclaration: {
47290
- description: 'RegExp string to detect import declarations for which this rule should be applied',
47291
- type: 'string',
47292
- },
47293
- projectName: {
47294
- description: 'RegExp string to extract project name from import',
47295
- type: 'string',
47296
- },
47297
- },
47298
- type: 'object',
47299
- },
47300
- ],
47301
- type: 'problem',
47302
- },
47303
- name: 'no-deep-imports',
47304
- });
47305
-
47306
47004
  function commonjsRequire(path) {
47307
47005
  throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
47308
47006
  }
@@ -247947,12 +247645,1056 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
247947
247645
  var typescriptExports = typescript.exports;
247948
247646
  var ts = /*@__PURE__*/getDefaultExportFromCjs(typescriptExports);
247949
247647
 
247648
+ function getResolvedVariable(sourceCode, node) {
247649
+ const scope = sourceCode.getScope(node);
247650
+ const reference = scope.references.find((item) => item.identifier === node);
247651
+ return reference?.resolved ?? null;
247652
+ }
247653
+
247654
+ function getTypeAwareRuleContext(context) {
247655
+ const parserServices = dist$3.ESLintUtils.getParserServices(context);
247656
+ const { sourceCode } = context;
247657
+ return {
247658
+ checker: parserServices.program.getTypeChecker(),
247659
+ esTreeNodeToTSNodeMap: parserServices.esTreeNodeToTSNodeMap,
247660
+ parserServices,
247661
+ program: sourceCode.ast,
247662
+ sourceCode,
247663
+ tsNodeToESTreeNodeMap: parserServices.tsNodeToESTreeNodeMap,
247664
+ tsProgram: parserServices.program,
247665
+ };
247666
+ }
247667
+
247668
+ const importGraphCacheByProgram = new WeakMap();
247669
+ const defaultExportCacheByProgram = new WeakMap();
247670
+ const moduleExportNamesCache = new WeakMap();
247671
+ const resolutionStateByProgram = new WeakMap();
247672
+ const sourceFileCacheByProgram = new WeakMap();
247673
+ const codeFileExtensionRegExp = /\.[cm]?[jt]sx?$/;
247674
+ // Angular DI functions resolve tokens at instantiation time, not at module load time,
247675
+ // so cycles where all usages are DI-only are safe and should not be reported.
247676
+ const ANGULAR_DI_FIRST_ARG_FUNCTIONS = new Set([
247677
+ 'contentChild',
247678
+ 'contentChildren',
247679
+ 'inject',
247680
+ 'viewChild',
247681
+ 'viewChildren',
247682
+ ]);
247683
+ function createCanonicalFileName() {
247684
+ const useCaseSensitiveFileNames = ts.sys.useCaseSensitiveFileNames;
247685
+ return (fileName) => {
247686
+ const resolvedFileName = path.resolve(fileName).replaceAll('\\', '/');
247687
+ return useCaseSensitiveFileNames
247688
+ ? resolvedFileName
247689
+ : resolvedFileName.toLowerCase();
247690
+ };
247691
+ }
247692
+ function getResolutionState(program) {
247693
+ const cached = resolutionStateByProgram.get(program);
247694
+ if (cached) {
247695
+ return cached;
247696
+ }
247697
+ const compilerOptions = program.getCompilerOptions();
247698
+ const state = {
247699
+ compilerHost: ts.createCompilerHost(compilerOptions, true),
247700
+ resolutionCache: ts.createModuleResolutionCache(program.getCurrentDirectory(), (fileName) => fileName, compilerOptions),
247701
+ };
247702
+ resolutionStateByProgram.set(program, state);
247703
+ return state;
247704
+ }
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
+ function resolveModule(program, containingFile, moduleSpecifier) {
247715
+ const compilerOptions = program.getCompilerOptions();
247716
+ const { compilerHost, resolutionCache } = getResolutionState(program);
247717
+ const resolved = ts.resolveModuleName(moduleSpecifier, containingFile, compilerOptions, compilerHost, resolutionCache).resolvedModule ?? null;
247718
+ return resolved;
247719
+ }
247720
+ function resolveModuleFileName(program, containingFile, moduleSpecifier) {
247721
+ const resolved = resolveModule(program, containingFile, moduleSpecifier);
247722
+ if (!resolved || resolved.isExternalLibraryImport) {
247723
+ return null;
247724
+ }
247725
+ return resolved.resolvedFileName;
247726
+ }
247727
+ function importDeclarationHasRuntimeEdge(node) {
247728
+ const importClause = node.importClause;
247729
+ if (!importClause) {
247730
+ return true;
247731
+ }
247732
+ if (importClause.isTypeOnly) {
247733
+ return false;
247734
+ }
247735
+ if (importClause.name) {
247736
+ return true;
247737
+ }
247738
+ const namedBindings = importClause.namedBindings;
247739
+ if (!namedBindings) {
247740
+ return false;
247741
+ }
247742
+ if (ts.isNamespaceImport(namedBindings)) {
247743
+ return true;
247744
+ }
247745
+ return (namedBindings.elements.length === 0 ||
247746
+ namedBindings.elements.some((specifier) => !specifier.isTypeOnly));
247747
+ }
247748
+ function exportDeclarationHasRuntimeEdge(node) {
247749
+ if (node.isTypeOnly) {
247750
+ return false;
247751
+ }
247752
+ const exportClause = node.exportClause;
247753
+ if (!exportClause || ts.isNamespaceExport(exportClause)) {
247754
+ return true;
247755
+ }
247756
+ return (exportClause.elements.length === 0 ||
247757
+ exportClause.elements.some((specifier) => !specifier.isTypeOnly));
247758
+ }
247759
+ function getRuntimeModuleSpecifier(statement) {
247760
+ if (ts.isImportDeclaration(statement)) {
247761
+ const { moduleSpecifier } = statement;
247762
+ return ts.isStringLiteralLike(moduleSpecifier) &&
247763
+ importDeclarationHasRuntimeEdge(statement)
247764
+ ? moduleSpecifier.text
247765
+ : null;
247766
+ }
247767
+ if (ts.isExportDeclaration(statement)) {
247768
+ const { moduleSpecifier } = statement;
247769
+ return moduleSpecifier &&
247770
+ ts.isStringLiteralLike(moduleSpecifier) &&
247771
+ exportDeclarationHasRuntimeEdge(statement)
247772
+ ? moduleSpecifier.text
247773
+ : null;
247774
+ }
247775
+ if (ts.isImportEqualsDeclaration(statement) &&
247776
+ !statement.isTypeOnly &&
247777
+ ts.isExternalModuleReference(statement.moduleReference)) {
247778
+ const expression = statement.moduleReference.expression;
247779
+ return ts.isStringLiteralLike(expression) ? expression.text : null;
247780
+ }
247781
+ return null;
247782
+ }
247783
+ function buildDependenciesByFileName(program, canonicalFileName) {
247784
+ const sourceFiles = program.getSourceFiles().filter(isProjectCodeFile);
247785
+ const projectFileNames = new Set(sourceFiles.map((sourceFile) => canonicalFileName(sourceFile.fileName)));
247786
+ const dependenciesByFileName = new Map();
247787
+ const displayFileNameByFileName = new Map();
247788
+ for (const sourceFile of sourceFiles) {
247789
+ const fileName = canonicalFileName(sourceFile.fileName);
247790
+ const edges = [];
247791
+ displayFileNameByFileName.set(fileName, sourceFile.fileName);
247792
+ for (const statement of sourceFile.statements) {
247793
+ const moduleSpecifier = getRuntimeModuleSpecifier(statement);
247794
+ if (!moduleSpecifier) {
247795
+ continue;
247796
+ }
247797
+ const resolvedFileName = resolveModuleFileName(program, sourceFile.fileName, moduleSpecifier);
247798
+ if (!resolvedFileName) {
247799
+ continue;
247800
+ }
247801
+ const targetFileName = canonicalFileName(resolvedFileName);
247802
+ if (!projectFileNames.has(targetFileName)) {
247803
+ continue;
247804
+ }
247805
+ edges.push({ moduleSpecifier, targetFileName });
247806
+ }
247807
+ dependenciesByFileName.set(fileName, edges);
247808
+ }
247809
+ return { dependenciesByFileName, displayFileNameByFileName };
247810
+ }
247811
+ function findStronglyConnectedComponents(dependenciesByFileName) {
247812
+ let nextComponentId = 0;
247813
+ let nextIndex = 0;
247814
+ const componentIdByFileName = new Map();
247815
+ const componentSizeById = new Map();
247816
+ const nodeStateByFileName = new Map();
247817
+ const stack = [];
247818
+ function visit(fileName) {
247819
+ const state = {
247820
+ index: nextIndex,
247821
+ lowLink: nextIndex,
247822
+ onStack: true,
247823
+ };
247824
+ nextIndex += 1;
247825
+ nodeStateByFileName.set(fileName, state);
247826
+ stack.push(fileName);
247827
+ for (const edge of dependenciesByFileName.get(fileName) ?? []) {
247828
+ const targetState = nodeStateByFileName.get(edge.targetFileName);
247829
+ if (!targetState) {
247830
+ visit(edge.targetFileName);
247831
+ const visitedTargetState = nodeStateByFileName.get(edge.targetFileName);
247832
+ if (visitedTargetState) {
247833
+ state.lowLink = Math.min(state.lowLink, visitedTargetState.lowLink);
247834
+ }
247835
+ continue;
247836
+ }
247837
+ if (targetState.onStack) {
247838
+ state.lowLink = Math.min(state.lowLink, targetState.index);
247839
+ }
247840
+ }
247841
+ if (state.lowLink !== state.index) {
247842
+ return;
247843
+ }
247844
+ const componentId = nextComponentId;
247845
+ let componentSize = 0;
247846
+ let shouldPop = stack.length > 0;
247847
+ nextComponentId += 1;
247848
+ while (shouldPop) {
247849
+ const memberFileName = stack.pop();
247850
+ if (!memberFileName) {
247851
+ shouldPop = false;
247852
+ continue;
247853
+ }
247854
+ const memberState = nodeStateByFileName.get(memberFileName);
247855
+ if (memberState) {
247856
+ memberState.onStack = false;
247857
+ }
247858
+ componentSize += 1;
247859
+ componentIdByFileName.set(memberFileName, componentId);
247860
+ shouldPop = stack.length > 0 && memberFileName !== fileName;
247861
+ }
247862
+ componentSizeById.set(componentId, componentSize);
247863
+ }
247864
+ for (const fileName of dependenciesByFileName.keys()) {
247865
+ if (!nodeStateByFileName.has(fileName)) {
247866
+ visit(fileName);
247867
+ }
247868
+ }
247869
+ return { componentIdByFileName, componentSizeById };
247870
+ }
247871
+ function collectSelfCycles(dependenciesByFileName) {
247872
+ const selfCycleFileNames = new Set();
247873
+ for (const [fileName, edges] of dependenciesByFileName) {
247874
+ if (edges.some((edge) => edge.targetFileName === fileName)) {
247875
+ selfCycleFileNames.add(fileName);
247876
+ }
247877
+ }
247878
+ return selfCycleFileNames;
247879
+ }
247880
+ function getImportGraph(program) {
247881
+ const cached = importGraphCacheByProgram.get(program);
247882
+ if (cached) {
247883
+ return cached;
247884
+ }
247885
+ const canonicalFileName = createCanonicalFileName();
247886
+ const { dependenciesByFileName, displayFileNameByFileName } = buildDependenciesByFileName(program, canonicalFileName);
247887
+ const { componentIdByFileName, componentSizeById } = findStronglyConnectedComponents(dependenciesByFileName);
247888
+ const cache = {
247889
+ componentIdByFileName,
247890
+ componentSizeById,
247891
+ dependenciesByFileName,
247892
+ displayFileNameByFileName,
247893
+ selfCycleFileNames: collectSelfCycles(dependenciesByFileName),
247894
+ };
247895
+ importGraphCacheByProgram.set(program, cache);
247896
+ return cache;
247897
+ }
247898
+ function getSourceFileByFileName(program, fileName) {
247899
+ const cached = sourceFileCacheByProgram.get(program);
247900
+ const canonicalFileName = createCanonicalFileName();
247901
+ const normalizedFileName = canonicalFileName(fileName);
247902
+ if (cached) {
247903
+ return cached.get(normalizedFileName) ?? null;
247904
+ }
247905
+ const sourceFileByFileName = new Map();
247906
+ for (const sourceFile of program.getSourceFiles()) {
247907
+ sourceFileByFileName.set(canonicalFileName(sourceFile.fileName), sourceFile);
247908
+ }
247909
+ sourceFileCacheByProgram.set(program, sourceFileByFileName);
247910
+ return sourceFileByFileName.get(normalizedFileName) ?? null;
247911
+ }
247912
+ function hasModifier(node, kind) {
247913
+ return (ts.canHaveModifiers(node) &&
247914
+ (ts.getModifiers(node)?.some((modifier) => modifier.kind === kind) ?? false));
247915
+ }
247916
+ function hasRuntimeDefaultModifier(statement) {
247917
+ return (hasModifier(statement, ts.SyntaxKind.ExportKeyword) &&
247918
+ hasModifier(statement, ts.SyntaxKind.DefaultKeyword) &&
247919
+ !ts.isInterfaceDeclaration(statement) &&
247920
+ !ts.isTypeAliasDeclaration(statement));
247921
+ }
247922
+ function exportsDefaultSpecifier(node) {
247923
+ if (node.isTypeOnly || !node.exportClause || !ts.isNamedExports(node.exportClause)) {
247924
+ return false;
247925
+ }
247926
+ return node.exportClause.elements.some((specifier) => !specifier.isTypeOnly && specifier.name.text === 'default');
247927
+ }
247928
+ function sourceFileHasDefaultExport(sourceFile) {
247929
+ return sourceFile.statements.some((statement) => (ts.isExportAssignment(statement) && !statement.isExportEquals) ||
247930
+ hasRuntimeDefaultModifier(statement) ||
247931
+ (ts.isExportDeclaration(statement) && exportsDefaultSpecifier(statement)));
247932
+ }
247933
+ function hasDefaultExport(program, fileName) {
247934
+ const canonicalFileName = createCanonicalFileName();
247935
+ const normalizedFileName = canonicalFileName(fileName);
247936
+ let cache = defaultExportCacheByProgram.get(program);
247937
+ if (!cache) {
247938
+ cache = new Map();
247939
+ defaultExportCacheByProgram.set(program, cache);
247940
+ }
247941
+ const cached = cache.get(normalizedFileName);
247942
+ if (cached !== undefined) {
247943
+ return cached;
247944
+ }
247945
+ const sourceFile = getSourceFileByFileName(program, fileName);
247946
+ const hasExport = sourceFile ? sourceFileHasDefaultExport(sourceFile) : false;
247947
+ cache.set(normalizedFileName, hasExport);
247948
+ return hasExport;
247949
+ }
247950
+ function hasRuntimeEstreeImport(node) {
247951
+ if (node.importKind === 'type') {
247952
+ return false;
247953
+ }
247954
+ if (node.specifiers.length === 0) {
247955
+ return true;
247956
+ }
247957
+ return node.specifiers.some((specifier) => {
247958
+ if (specifier.type !== dist$3.AST_NODE_TYPES.ImportSpecifier) {
247959
+ return true;
247960
+ }
247961
+ return specifier.importKind !== 'type';
247962
+ });
247963
+ }
247964
+ function hasRuntimeEstreeReExport(node) {
247965
+ if (node.exportKind === 'type') {
247966
+ return false;
247967
+ }
247968
+ if (node.type === dist$3.AST_NODE_TYPES.ExportAllDeclaration) {
247969
+ return true;
247970
+ }
247971
+ return (node.specifiers.length === 0 ||
247972
+ node.specifiers.some((specifier) => specifier.exportKind !== 'type'));
247973
+ }
247974
+ function getImportOrReExportModuleSpecifier(node) {
247975
+ if (node.type === dist$3.AST_NODE_TYPES.ImportDeclaration) {
247976
+ return hasRuntimeEstreeImport(node) ? node.source.value : null;
247977
+ }
247978
+ if (!node.source || !hasRuntimeEstreeReExport(node)) {
247979
+ return null;
247980
+ }
247981
+ return typeof node.source.value === 'string' ? node.source.value : null;
247982
+ }
247983
+ function findCyclicTargetFileName(graph, currentFileName, moduleSpecifier) {
247984
+ const currentComponentId = graph.componentIdByFileName.get(currentFileName);
247985
+ if (currentComponentId === undefined) {
247986
+ return null;
247987
+ }
247988
+ const currentComponentSize = graph.componentSizeById.get(currentComponentId) ?? 0;
247989
+ for (const edge of graph.dependenciesByFileName.get(currentFileName) ?? []) {
247990
+ if (edge.moduleSpecifier !== moduleSpecifier) {
247991
+ continue;
247992
+ }
247993
+ const isSelfCycle = edge.targetFileName === currentFileName &&
247994
+ graph.selfCycleFileNames.has(currentFileName);
247995
+ const isSameComponentCycle = currentComponentSize > 1 &&
247996
+ graph.componentIdByFileName.get(edge.targetFileName) === currentComponentId;
247997
+ if (isSelfCycle || isSameComponentCycle) {
247998
+ return edge.targetFileName;
247999
+ }
248000
+ }
248001
+ return null;
248002
+ }
248003
+ function findPathWithinComponent(graph, startFileName, endFileName, componentId) {
248004
+ const queue = [startFileName];
248005
+ const previousFileName = new Map([[startFileName, null]]);
248006
+ for (let index = 0; index < queue.length && !previousFileName.has(endFileName); index += 1) {
248007
+ const currentFileName = queue[index];
248008
+ if (!currentFileName) {
248009
+ continue;
248010
+ }
248011
+ for (const edge of graph.dependenciesByFileName.get(currentFileName) ?? []) {
248012
+ if (graph.componentIdByFileName.get(edge.targetFileName) !== componentId ||
248013
+ previousFileName.has(edge.targetFileName)) {
248014
+ continue;
248015
+ }
248016
+ previousFileName.set(edge.targetFileName, currentFileName);
248017
+ queue.push(edge.targetFileName);
248018
+ }
248019
+ }
248020
+ if (!previousFileName.has(endFileName)) {
248021
+ return [startFileName, endFileName];
248022
+ }
248023
+ const pathSegments = [];
248024
+ let currentFileName = endFileName;
248025
+ while (currentFileName !== null) {
248026
+ pathSegments.push(currentFileName);
248027
+ const nextFileName = previousFileName.get(currentFileName);
248028
+ if (nextFileName === undefined) {
248029
+ return [startFileName, endFileName];
248030
+ }
248031
+ currentFileName = nextFileName;
248032
+ }
248033
+ return pathSegments.reverse();
248034
+ }
248035
+ function formatFileName(graph, fileName, cwd) {
248036
+ const displayFileName = graph.displayFileNameByFileName.get(fileName) ?? fileName;
248037
+ const relativeFileName = normalizeSlashes(path.relative(cwd, displayFileName));
248038
+ return relativeFileName || normalizeSlashes(path.basename(displayFileName));
248039
+ }
248040
+ function formatCyclePath(graph, currentFileName, targetFileName, cwd) {
248041
+ const componentId = graph.componentIdByFileName.get(currentFileName);
248042
+ if (componentId === undefined || currentFileName === targetFileName) {
248043
+ return [currentFileName, targetFileName]
248044
+ .map((fileName) => formatFileName(graph, fileName, cwd))
248045
+ .join(' -> ');
248046
+ }
248047
+ return [
248048
+ currentFileName,
248049
+ ...findPathWithinComponent(graph, targetFileName, currentFileName, componentId),
248050
+ ]
248051
+ .map((fileName) => formatFileName(graph, fileName, cwd))
248052
+ .join(' -> ');
248053
+ }
248054
+ function getAliasedSymbolIfNeeded(checker, symbol) {
248055
+ return (symbol.flags & ts.SymbolFlags.Alias) === 0
248056
+ ? symbol
248057
+ : checker.getAliasedSymbol(symbol);
248058
+ }
248059
+ function isValueExport(checker, symbol) {
248060
+ const exportSymbol = getAliasedSymbolIfNeeded(checker, symbol);
248061
+ return (exportSymbol.flags & ts.SymbolFlags.Value) !== 0;
248062
+ }
248063
+ function getModuleExportNames(checker, moduleSymbol) {
248064
+ const symbol = getAliasedSymbolIfNeeded(checker, moduleSymbol);
248065
+ const cached = moduleExportNamesCache.get(symbol);
248066
+ if (cached) {
248067
+ return cached;
248068
+ }
248069
+ const exportNames = new Set(checker
248070
+ .getExportsOfModule(symbol)
248071
+ .filter((exportSymbol) => isValueExport(checker, exportSymbol))
248072
+ .map((exportSymbol) => exportSymbol.escapedName.toString()));
248073
+ moduleExportNamesCache.set(symbol, exportNames);
248074
+ return exportNames;
248075
+ }
248076
+ function getNamespaceImportExportNames(checker, esTreeNodeToTSNodeMap, node) {
248077
+ if (node.importKind === 'type') {
248078
+ return null;
248079
+ }
248080
+ const tsNode = esTreeNodeToTSNodeMap.get(node);
248081
+ if (!ts.isImportDeclaration(tsNode)) {
248082
+ return null;
248083
+ }
248084
+ const moduleSymbol = checker.getSymbolAtLocation(tsNode.moduleSpecifier);
248085
+ return moduleSymbol ? getModuleExportNames(checker, moduleSymbol) : null;
248086
+ }
248087
+ function getExportDeclarationModuleExportNames(checker, esTreeNodeToTSNodeMap, node) {
248088
+ const tsNode = esTreeNodeToTSNodeMap.get(node);
248089
+ if (!ts.isExportDeclaration(tsNode) ||
248090
+ !tsNode.moduleSpecifier ||
248091
+ !ts.isStringLiteralLike(tsNode.moduleSpecifier)) {
248092
+ return null;
248093
+ }
248094
+ const moduleSymbol = checker.getSymbolAtLocation(tsNode.moduleSpecifier);
248095
+ return moduleSymbol ? getModuleExportNames(checker, moduleSymbol) : null;
248096
+ }
248097
+ function getExportSpecifierName(name) {
248098
+ if (name.type === dist$3.AST_NODE_TYPES.Identifier) {
248099
+ return name.name;
248100
+ }
248101
+ return typeof name.value === 'string' ? name.value : null;
248102
+ }
248103
+ function hasNamedValueExport(exportNames, exportedName) {
248104
+ return exportedName !== 'default' && (exportNames?.has(exportedName) ?? false);
248105
+ }
248106
+ function isImportUsedOnlyAsAngularDiFirstArg(node, sourceCode) {
248107
+ const valueSpecifiers = node.specifiers.filter((specifier) => {
248108
+ if (specifier.type === dist$3.AST_NODE_TYPES.ImportDefaultSpecifier ||
248109
+ specifier.type === dist$3.AST_NODE_TYPES.ImportNamespaceSpecifier) {
248110
+ return true;
248111
+ }
248112
+ return specifier.importKind !== 'type';
248113
+ });
248114
+ if (valueSpecifiers.length === 0) {
248115
+ return false;
248116
+ }
248117
+ for (const specifier of valueSpecifiers) {
248118
+ const [variable] = sourceCode.getDeclaredVariables(specifier);
248119
+ if (!variable || variable.references.length === 0) {
248120
+ return false;
248121
+ }
248122
+ for (const ref of variable.references) {
248123
+ const { identifier } = ref;
248124
+ const parent = identifier.parent;
248125
+ const callee = parent.type === dist$3.AST_NODE_TYPES.CallExpression ? parent.callee : null;
248126
+ const isDirectCall = callee?.type === dist$3.AST_NODE_TYPES.Identifier &&
248127
+ ANGULAR_DI_FIRST_ARG_FUNCTIONS.has(callee.name);
248128
+ const isRequiredCall = callee?.type === dist$3.AST_NODE_TYPES.MemberExpression &&
248129
+ !callee.computed &&
248130
+ callee.object.type === dist$3.AST_NODE_TYPES.Identifier &&
248131
+ ANGULAR_DI_FIRST_ARG_FUNCTIONS.has(callee.object.name) &&
248132
+ callee.property.type === dist$3.AST_NODE_TYPES.Identifier &&
248133
+ callee.property.name === 'required';
248134
+ if (parent.type !== dist$3.AST_NODE_TYPES.CallExpression ||
248135
+ (!isDirectCall && !isRequiredCall) ||
248136
+ parent.arguments[0] !== identifier) {
248137
+ return false;
248138
+ }
248139
+ }
248140
+ }
248141
+ return true;
248142
+ }
248143
+ const rule$K = createRule({
248144
+ create(context) {
248145
+ const { checker, esTreeNodeToTSNodeMap, sourceCode, tsProgram } = getTypeAwareRuleContext(context);
248146
+ const checkCycles = context.options[0]?.checkCycles ?? true;
248147
+ const checkDefaultImports = context.options[0]?.checkDefaultImports ?? true;
248148
+ const checkNamedAsDefault = context.options[0]?.checkNamedAsDefault ?? true;
248149
+ const checkNamespaceMembers = context.options[0]?.checkNamespaceMembers ?? true;
248150
+ const ignoreExternalDefaultImports = context.options[0]?.ignoreExternalDefaultImports ?? true;
248151
+ const canonicalFileName = createCanonicalFileName();
248152
+ const currentFileName = canonicalFileName(context.filename);
248153
+ const namespaceImports = new Map();
248154
+ function checkImportCycle(node) {
248155
+ if (!checkCycles) {
248156
+ return;
248157
+ }
248158
+ const moduleSpecifier = getImportOrReExportModuleSpecifier(node);
248159
+ if (!moduleSpecifier) {
248160
+ return;
248161
+ }
248162
+ const sourceNode = node.source;
248163
+ if (!sourceNode) {
248164
+ return;
248165
+ }
248166
+ const graph = getImportGraph(tsProgram);
248167
+ const targetFileName = findCyclicTargetFileName(graph, currentFileName, moduleSpecifier);
248168
+ if (!targetFileName ||
248169
+ (node.type === dist$3.AST_NODE_TYPES.ImportDeclaration &&
248170
+ isImportUsedOnlyAsAngularDiFirstArg(node, sourceCode))) {
248171
+ return;
248172
+ }
248173
+ context.report({
248174
+ data: {
248175
+ cyclePath: formatCyclePath(graph, currentFileName, targetFileName, context.cwd),
248176
+ },
248177
+ messageId: 'importCycle',
248178
+ node: sourceNode,
248179
+ });
248180
+ }
248181
+ function checkDefaultImport(node) {
248182
+ if ((!checkDefaultImports && !checkNamedAsDefault) ||
248183
+ node.importKind === 'type') {
248184
+ return;
248185
+ }
248186
+ const defaultImport = node.specifiers.find((specifier) => specifier.type === dist$3.AST_NODE_TYPES.ImportDefaultSpecifier);
248187
+ if (!defaultImport) {
248188
+ return;
248189
+ }
248190
+ const moduleSpecifier = node.source.value;
248191
+ const resolved = resolveModule(tsProgram, context.filename, moduleSpecifier);
248192
+ if (!resolved ||
248193
+ (resolved.isExternalLibraryImport && ignoreExternalDefaultImports)) {
248194
+ return;
248195
+ }
248196
+ const hasResolvedDefaultExport = hasDefaultExport(tsProgram, resolved.resolvedFileName);
248197
+ if (!hasResolvedDefaultExport) {
248198
+ if (!checkDefaultImports) {
248199
+ return;
248200
+ }
248201
+ context.report({
248202
+ data: { moduleSpecifier },
248203
+ messageId: 'missingDefaultExport',
248204
+ node: defaultImport,
248205
+ });
248206
+ return;
248207
+ }
248208
+ const exportNames = getNamespaceImportExportNames(checker, esTreeNodeToTSNodeMap, node);
248209
+ if (!checkNamedAsDefault ||
248210
+ !hasNamedValueExport(exportNames, defaultImport.local.name)) {
248211
+ return;
248212
+ }
248213
+ context.report({
248214
+ data: { name: defaultImport.local.name },
248215
+ messageId: 'namedAsDefault',
248216
+ node: defaultImport,
248217
+ });
248218
+ }
248219
+ function checkNamedAsDefaultExport(node) {
248220
+ if (!checkNamedAsDefault ||
248221
+ node.exportKind === 'type' ||
248222
+ !node.source ||
248223
+ typeof node.source.value !== 'string') {
248224
+ return;
248225
+ }
248226
+ const moduleSpecifier = node.source.value;
248227
+ const resolved = resolveModule(tsProgram, context.filename, moduleSpecifier);
248228
+ if (!resolved ||
248229
+ (resolved.isExternalLibraryImport && ignoreExternalDefaultImports) ||
248230
+ !hasDefaultExport(tsProgram, resolved.resolvedFileName)) {
248231
+ return;
248232
+ }
248233
+ const exportNames = getExportDeclarationModuleExportNames(checker, esTreeNodeToTSNodeMap, node);
248234
+ for (const specifier of node.specifiers) {
248235
+ if (specifier.exportKind === 'type' ||
248236
+ getExportSpecifierName(specifier.local) !== 'default') {
248237
+ continue;
248238
+ }
248239
+ const exportedName = getExportSpecifierName(specifier.exported);
248240
+ if (!exportedName || !hasNamedValueExport(exportNames, exportedName)) {
248241
+ continue;
248242
+ }
248243
+ context.report({
248244
+ data: { name: exportedName },
248245
+ messageId: 'namedAsDefault',
248246
+ node: specifier.exported,
248247
+ });
248248
+ }
248249
+ }
248250
+ function collectNamespaceImport(node) {
248251
+ if (!checkNamespaceMembers) {
248252
+ return;
248253
+ }
248254
+ const namespaceImport = node.specifiers.find((specifier) => specifier.type === dist$3.AST_NODE_TYPES.ImportNamespaceSpecifier);
248255
+ if (!namespaceImport) {
248256
+ return;
248257
+ }
248258
+ const exportNames = getNamespaceImportExportNames(checker, esTreeNodeToTSNodeMap, node);
248259
+ if (!exportNames) {
248260
+ return;
248261
+ }
248262
+ const [variable] = sourceCode.getDeclaredVariables(namespaceImport);
248263
+ if (!variable) {
248264
+ return;
248265
+ }
248266
+ namespaceImports.set(namespaceImport.local.name, {
248267
+ exportNames,
248268
+ moduleSpecifier: node.source.value,
248269
+ node: namespaceImport,
248270
+ variable,
248271
+ });
248272
+ }
248273
+ function buildNamespaceToNamedFix(fixer, usage) {
248274
+ const importDecl = usage.node.parent;
248275
+ if (importDecl.specifiers.length !== 1) {
248276
+ return null;
248277
+ }
248278
+ const memberNames = new Set();
248279
+ const memberNodes = [];
248280
+ for (const ref of usage.variable.references) {
248281
+ const parent = ref.identifier.parent;
248282
+ if (parent.type !== dist$3.AST_NODE_TYPES.MemberExpression ||
248283
+ parent.object !== ref.identifier ||
248284
+ parent.computed) {
248285
+ return null;
248286
+ }
248287
+ const memberName = getMemberExpressionPropertyName(parent);
248288
+ if (!memberName || memberName === 'default') {
248289
+ return null;
248290
+ }
248291
+ memberNames.add(memberName);
248292
+ memberNodes.push(parent);
248293
+ }
248294
+ if (memberNames.size === 0) {
248295
+ return null;
248296
+ }
248297
+ const sourceText = sourceCode.getText(importDecl.source);
248298
+ const hasSemi = sourceCode.getText(importDecl).endsWith(';');
248299
+ const sortedMembers = [...memberNames].sort();
248300
+ const newImportText = `import {${sortedMembers.join(', ')}} from ${sourceText}${hasSemi ? ';' : ''}`;
248301
+ return [
248302
+ fixer.replaceText(importDecl, newImportText),
248303
+ ...memberNodes.flatMap((memberNode) => {
248304
+ const name = getMemberExpressionPropertyName(memberNode);
248305
+ return name ? [fixer.replaceText(memberNode, name)] : [];
248306
+ }),
248307
+ ];
248308
+ }
248309
+ function checkNamespaceMember(node) {
248310
+ if (!checkNamespaceMembers ||
248311
+ node.object.type !== dist$3.AST_NODE_TYPES.Identifier) {
248312
+ return;
248313
+ }
248314
+ const usage = namespaceImports.get(node.object.name);
248315
+ const memberName = getMemberExpressionPropertyName(node);
248316
+ if (!usage ||
248317
+ !memberName ||
248318
+ usage.exportNames.has(memberName) ||
248319
+ getResolvedVariable(sourceCode, node.object) !== usage.variable) {
248320
+ return;
248321
+ }
248322
+ context.report({
248323
+ data: {
248324
+ memberName,
248325
+ moduleSpecifier: usage.moduleSpecifier,
248326
+ namespaceName: usage.node.local.name,
248327
+ },
248328
+ fix: (fixer) => buildNamespaceToNamedFix(fixer, usage),
248329
+ messageId: 'unknownNamespaceMember',
248330
+ node: node.property,
248331
+ });
248332
+ }
248333
+ return {
248334
+ ExportAllDeclaration: checkImportCycle,
248335
+ ExportNamedDeclaration(node) {
248336
+ checkImportCycle(node);
248337
+ checkNamedAsDefaultExport(node);
248338
+ },
248339
+ ImportDeclaration(node) {
248340
+ checkImportCycle(node);
248341
+ checkDefaultImport(node);
248342
+ collectNamespaceImport(node);
248343
+ },
248344
+ MemberExpression: checkNamespaceMember,
248345
+ };
248346
+ },
248347
+ meta: {
248348
+ docs: {
248349
+ description: 'Fast replacement for import/default, import/namespace, import/no-cycle, and import/no-named-as-default checks',
248350
+ },
248351
+ fixable: 'code',
248352
+ messages: {
248353
+ importCycle: 'Import cycle detected: {{cyclePath}}.',
248354
+ missingDefaultExport: 'No default export found in "{{moduleSpecifier}}".',
248355
+ namedAsDefault: 'Using exported name "{{name}}" as identifier for default export.',
248356
+ unknownNamespaceMember: 'Namespace import "{{namespaceName}}" from "{{moduleSpecifier}}" has no exported member "{{memberName}}".',
248357
+ },
248358
+ schema: [
248359
+ {
248360
+ additionalProperties: false,
248361
+ properties: {
248362
+ checkCycles: {
248363
+ description: 'Report static project-local import and re-export cycles. Defaults to true.',
248364
+ type: 'boolean',
248365
+ },
248366
+ checkDefaultImports: {
248367
+ description: 'Report default imports from modules without a default export. Defaults to true.',
248368
+ type: 'boolean',
248369
+ },
248370
+ checkNamedAsDefault: {
248371
+ description: 'Report default imports and default re-exports named after a named export from the same module. Defaults to true.',
248372
+ type: 'boolean',
248373
+ },
248374
+ checkNamespaceMembers: {
248375
+ description: 'Report static namespace import member accesses that are not exported by the imported module. Defaults to true.',
248376
+ type: 'boolean',
248377
+ },
248378
+ ignoreExternalDefaultImports: {
248379
+ description: 'Skip default import checks for modules resolved from external libraries. Defaults to true.',
248380
+ type: 'boolean',
248381
+ },
248382
+ },
248383
+ type: 'object',
248384
+ },
248385
+ ],
248386
+ type: 'problem',
248387
+ },
248388
+ name: 'import-integrity',
248389
+ });
248390
+
248391
+ const MESSAGE_ID$e = 'invalid-injection-token-description';
248392
+ const ERROR_MESSAGE$3 = "InjectionToken's description should contain token's name";
248393
+ const NG_DEV_MODE = 'ngDevMode';
248394
+ function getVariableName(node) {
248395
+ if (node.parent.type !== dist$2.AST_NODE_TYPES.VariableDeclarator) {
248396
+ return undefined;
248397
+ }
248398
+ const { id } = node.parent;
248399
+ return id.type === dist$2.AST_NODE_TYPES.Identifier ? id.name : undefined;
248400
+ }
248401
+ function isStringLike(node) {
248402
+ return isStringLiteral(node) || node.type === dist$2.AST_NODE_TYPES.TemplateLiteral;
248403
+ }
248404
+ function getStringValue(node) {
248405
+ if (isStringLiteral(node)) {
248406
+ return node.value;
248407
+ }
248408
+ return node.quasis[0]?.value.raw || '';
248409
+ }
248410
+ function isEmptyString(node) {
248411
+ return (isEmptyStaticString(node) &&
248412
+ (!('expressions' in node) || node.expressions.length === 0));
248413
+ }
248414
+ function isNgDevModeConditional(node) {
248415
+ return (node.type === dist$2.AST_NODE_TYPES.ConditionalExpression &&
248416
+ node.test.type === dist$2.AST_NODE_TYPES.Identifier &&
248417
+ node.test.name === NG_DEV_MODE &&
248418
+ isStringLike(node.consequent) &&
248419
+ isStringLike(node.alternate) &&
248420
+ isEmptyString(node.alternate));
248421
+ }
248422
+ function getDescriptionValue(node) {
248423
+ if (isStringLike(node)) {
248424
+ return getStringValue(node);
248425
+ }
248426
+ if (isNgDevModeConditional(node)) {
248427
+ return getStringValue(node.consequent);
248428
+ }
248429
+ return undefined;
248430
+ }
248431
+ function getDescriptionNode(node) {
248432
+ if (isStringLike(node)) {
248433
+ return node;
248434
+ }
248435
+ return isNgDevModeConditional(node) ? node.consequent : undefined;
248436
+ }
248437
+ function prependTokenName(text, name) {
248438
+ return `${text.slice(0, 1)}[${name}]: ${text.slice(1)}`;
248439
+ }
248440
+ function isNgDevModeVisible(sourceCode, node) {
248441
+ for (let scope = sourceCode.getScope(node); scope !== null; scope = scope.upper) {
248442
+ if (scope.variables.some((variable) => variable.name === NG_DEV_MODE)) {
248443
+ return true;
248444
+ }
248445
+ }
248446
+ return false;
248447
+ }
248448
+ function getNgDevModeDeclarationFix(program, fixer) {
248449
+ const lastImport = [...program.body]
248450
+ .reverse()
248451
+ .find((statement) => statement.type === dist$2.AST_NODE_TYPES.ImportDeclaration);
248452
+ if (lastImport) {
248453
+ return fixer.insertTextAfter(lastImport, '\n\ndeclare const ngDevMode: boolean;');
248454
+ }
248455
+ const [firstStatement] = program.body;
248456
+ if (firstStatement) {
248457
+ return fixer.insertTextBefore(firstStatement, 'declare const ngDevMode: boolean;\n\n');
248458
+ }
248459
+ return fixer.insertTextBeforeRange([0, 0], 'declare const ngDevMode: boolean;\n');
248460
+ }
248461
+ const rule$J = createRule({
248462
+ create(context) {
248463
+ const { sourceCode } = context;
248464
+ const program = sourceCode.ast;
248465
+ let shouldAddNgDevModeDeclaration = true;
248466
+ return {
248467
+ 'NewExpression[callee.name="InjectionToken"]'(node) {
248468
+ const [description] = node.arguments;
248469
+ if (!description || description.type === dist$2.AST_NODE_TYPES.SpreadElement) {
248470
+ return;
248471
+ }
248472
+ const name = getVariableName(node);
248473
+ const token = getDescriptionValue(description);
248474
+ const fixedDescription = getDescriptionNode(description);
248475
+ const report = name && token && !token.includes(name);
248476
+ if (report && fixedDescription) {
248477
+ context.report({
248478
+ fix: (fixer) => {
248479
+ const isNgDevModeGuarded = isNgDevModeConditional(description);
248480
+ const fixes = [
248481
+ fixer.replaceText(isNgDevModeGuarded ? fixedDescription : description, isNgDevModeGuarded
248482
+ ? prependTokenName(sourceCode.getText(fixedDescription), name)
248483
+ : `${NG_DEV_MODE} ? ${prependTokenName(sourceCode.getText(fixedDescription), name)} : ''`),
248484
+ ];
248485
+ if (!isNgDevModeGuarded &&
248486
+ shouldAddNgDevModeDeclaration &&
248487
+ !isNgDevModeVisible(sourceCode, description)) {
248488
+ shouldAddNgDevModeDeclaration = false;
248489
+ fixes.unshift(getNgDevModeDeclarationFix(program, fixer));
248490
+ }
248491
+ return fixes;
248492
+ },
248493
+ messageId: MESSAGE_ID$e,
248494
+ node: description,
248495
+ });
248496
+ }
248497
+ },
248498
+ };
248499
+ },
248500
+ meta: {
248501
+ docs: { description: ERROR_MESSAGE$3 },
248502
+ fixable: 'code',
248503
+ messages: { [MESSAGE_ID$e]: ERROR_MESSAGE$3 },
248504
+ schema: [],
248505
+ type: 'problem',
248506
+ },
248507
+ name: 'injection-token-description',
248508
+ });
248509
+
248510
+ const rule$I = createRule({
248511
+ create(context) {
248512
+ const { sourceCode } = context;
248513
+ const namespaceImports = new Map();
248514
+ const markNamespaceImportAsUsedLikeValue = (identifier) => {
248515
+ const usage = namespaceImports.get(identifier.name);
248516
+ if (!usage ||
248517
+ usage.usedLikeValue ||
248518
+ getResolvedVariable(sourceCode, identifier) !== usage.variable) {
248519
+ return;
248520
+ }
248521
+ usage.usedLikeValue = true;
248522
+ };
248523
+ return {
248524
+ 'CallExpression > Identifier.callee'(node) {
248525
+ markNamespaceImportAsUsedLikeValue(node);
248526
+ },
248527
+ ImportDeclaration(node) {
248528
+ const namespaceImport = node.specifiers.find((specifier) => specifier.type === dist$3.AST_NODE_TYPES.ImportNamespaceSpecifier);
248529
+ if (!namespaceImport) {
248530
+ return;
248531
+ }
248532
+ const [variable] = sourceCode.getDeclaredVariables(namespaceImport);
248533
+ if (!variable) {
248534
+ return;
248535
+ }
248536
+ namespaceImports.set(namespaceImport.local.name, {
248537
+ node: namespaceImport,
248538
+ usedLikeValue: false,
248539
+ variable,
248540
+ });
248541
+ },
248542
+ 'NewExpression > Identifier.callee'(node) {
248543
+ markNamespaceImportAsUsedLikeValue(node);
248544
+ },
248545
+ 'Program:exit'() {
248546
+ for (const usage of namespaceImports.values()) {
248547
+ if (!usage.usedLikeValue) {
248548
+ continue;
248549
+ }
248550
+ context.report({
248551
+ data: { name: usage.node.local.name },
248552
+ messageId: 'avoidCallableNamespaceImport',
248553
+ node: usage.node,
248554
+ });
248555
+ }
248556
+ },
248557
+ 'TaggedTemplateExpression > Identifier.tag'(node) {
248558
+ markNamespaceImportAsUsedLikeValue(node);
248559
+ },
248560
+ TSImportEqualsDeclaration(node) {
248561
+ if (node.moduleReference.type !== dist$3.AST_NODE_TYPES.TSExternalModuleReference) {
248562
+ return;
248563
+ }
248564
+ context.report({
248565
+ data: { name: node.id.name },
248566
+ messageId: 'avoidImportEquals',
248567
+ node,
248568
+ });
248569
+ },
248570
+ };
248571
+ },
248572
+ meta: {
248573
+ docs: {
248574
+ description: 'Disallow legacy CommonJS interop import patterns such as `import = require(...)` and namespace imports used like callable values.',
248575
+ },
248576
+ messages: {
248577
+ avoidCallableNamespaceImport: 'Namespace import "{{name}}" is used like a value instead of a namespace. This is a brittle interop pattern and often should become a default import.',
248578
+ avoidImportEquals: '`import {{name}} = require(...)` is a legacy CommonJS import pattern.',
248579
+ },
248580
+ schema: [],
248581
+ type: 'problem',
248582
+ },
248583
+ name: 'no-commonjs-import-patterns',
248584
+ });
248585
+
248586
+ const MESSAGE_ID$d = 'no-deep-imports';
248587
+ const ERROR_MESSAGE$2 = 'Deep imports of Taiga UI packages are prohibited';
248588
+ const CODE_EXTENSIONS = new Set([
248589
+ '.cjs',
248590
+ '.cts',
248591
+ '.js',
248592
+ '.jsx',
248593
+ '.mjs',
248594
+ '.mts',
248595
+ '.ts',
248596
+ '.tsx',
248597
+ ]);
248598
+ const DEFAULT_OPTIONS = {
248599
+ currentProject: '',
248600
+ deepImport: String.raw `(?<=^@taiga-ui/[\w-]+)(/.+)$`,
248601
+ ignoreImports: [],
248602
+ importDeclaration: '^@taiga-ui*',
248603
+ projectName: String.raw `(?<=^@taiga-ui/)([-\w]+)`,
248604
+ };
248605
+ const rule$H = createRule({
248606
+ create(context) {
248607
+ const { currentProject, deepImport, ignoreImports, importDeclaration, projectName, } = { ...DEFAULT_OPTIONS, ...context.options[0] };
248608
+ const hasNonCodeExtension = (source) => {
248609
+ if (!source) {
248610
+ return false;
248611
+ }
248612
+ const cleanSource = source.split(/[?#]/, 1)[0] ?? '';
248613
+ const extension = path.posix.extname(cleanSource).toLowerCase();
248614
+ return !!extension && !CODE_EXTENSIONS.has(extension);
248615
+ };
248616
+ const isDeepImport = (source) => !!source && new RegExp(deepImport, 'g').test(source);
248617
+ const isSideEffectImport = (node) => node.specifiers.length === 0;
248618
+ const isInsideTheSameEntryPoint = (source) => {
248619
+ const filePath = path
248620
+ .relative(context.cwd, context.filename)
248621
+ .replaceAll(/\\+/g, '/');
248622
+ const [currentFileProjectName] = (currentProject && new RegExp(currentProject, 'g').exec(filePath)) ?? [];
248623
+ const [importSourceProjectName] = source?.match(new RegExp(projectName, 'g')) ?? [];
248624
+ return Boolean(currentFileProjectName &&
248625
+ importSourceProjectName &&
248626
+ currentFileProjectName === importSourceProjectName);
248627
+ };
248628
+ const shouldIgnore = (source) => !!source && ignoreImports.some((p) => new RegExp(p, 'g').test(source));
248629
+ return {
248630
+ [`ImportDeclaration[source.value=/${importDeclaration}/]`](node) {
248631
+ if (!node || isSideEffectImport(node)) {
248632
+ return;
248633
+ }
248634
+ const importSource = node.source.value;
248635
+ if (!importSource ||
248636
+ !isDeepImport(importSource) ||
248637
+ isInsideTheSameEntryPoint(importSource) ||
248638
+ shouldIgnore(importSource) ||
248639
+ hasNonCodeExtension(importSource)) {
248640
+ return;
248641
+ }
248642
+ context.report({
248643
+ fix: (fixer) => {
248644
+ const [start, end] = node.source.range;
248645
+ return fixer.replaceTextRange([start + 1, end - 1], importSource.replaceAll(new RegExp(deepImport, 'g'), ''));
248646
+ },
248647
+ messageId: MESSAGE_ID$d,
248648
+ node: node.source,
248649
+ });
248650
+ },
248651
+ };
248652
+ },
248653
+ meta: {
248654
+ defaultOptions: [DEFAULT_OPTIONS],
248655
+ docs: { description: ERROR_MESSAGE$2 },
248656
+ fixable: 'code',
248657
+ messages: { [MESSAGE_ID$d]: ERROR_MESSAGE$2 },
248658
+ schema: [
248659
+ {
248660
+ additionalProperties: false,
248661
+ properties: {
248662
+ currentProject: {
248663
+ description: 'RegExp string to pick out current project name of processed file',
248664
+ type: 'string',
248665
+ },
248666
+ deepImport: {
248667
+ description: 'RegExp string to pick out deep import part',
248668
+ type: 'string',
248669
+ },
248670
+ ignoreImports: {
248671
+ description: 'RegExp string to exclude import declarations which is selected by importDeclaration-option',
248672
+ items: { type: 'string' },
248673
+ type: 'array',
248674
+ },
248675
+ importDeclaration: {
248676
+ description: 'RegExp string to detect import declarations for which this rule should be applied',
248677
+ type: 'string',
248678
+ },
248679
+ projectName: {
248680
+ description: 'RegExp string to extract project name from import',
248681
+ type: 'string',
248682
+ },
248683
+ },
248684
+ type: 'object',
248685
+ },
248686
+ ],
248687
+ type: 'problem',
248688
+ },
248689
+ name: 'no-deep-imports',
248690
+ });
248691
+
247950
248692
  const resolveCacheByOptions = new WeakMap();
247951
248693
  const nearestFileUpCache = new Map();
247952
248694
  const markerCache = new Map();
247953
248695
  const indexFileCache = new Map();
247954
248696
  const indexExportsCache = new Map();
247955
- const rule$E = createRule({
248697
+ const rule$G = createRule({
247956
248698
  create(context) {
247957
248699
  const parserServices = dist$3.ESLintUtils.getParserServices(context);
247958
248700
  const program = parserServices.program;
@@ -248149,13 +248891,13 @@ const noDuplicateAttributesRule = angular.templatePlugin.rules?.['no-duplicate-a
248149
248891
  if (!noDuplicateAttributesRule) {
248150
248892
  throw new Error('angular-eslint template rule "no-duplicate-attributes" is not available');
248151
248893
  }
248152
- const rule$D = createRule({
248894
+ const rule$F = createRule({
248153
248895
  name: 'no-duplicate-attrs',
248154
248896
  rule: noDuplicateAttributesRule,
248155
248897
  });
248156
248898
 
248157
248899
  const MESSAGE_ID$c = 'duplicateId';
248158
- const rule$C = createRule({
248900
+ const rule$E = createRule({
248159
248901
  name: 'no-duplicate-id',
248160
248902
  rule: {
248161
248903
  create(context) {
@@ -248217,7 +248959,7 @@ function getTrackingKey(node) {
248217
248959
  }
248218
248960
  return null;
248219
248961
  }
248220
- const rule$B = createRule({
248962
+ const rule$D = createRule({
248221
248963
  name: 'no-duplicate-in-head',
248222
248964
  rule: {
248223
248965
  create(context) {
@@ -248802,21 +249544,7 @@ const ANGULAR_SIGNALS_UNTRACKED_GUIDE_URL = 'https://angular.dev/guide/signals#r
248802
249544
  const ANGULAR_SIGNALS_ASYNC_GUIDE_URL = 'https://angular.dev/guide/signals#reactive-context-and-async-operations';
248803
249545
  const createUntrackedRule = createRule;
248804
249546
 
248805
- function getTypeAwareRuleContext(context) {
248806
- const parserServices = dist$3.ESLintUtils.getParserServices(context);
248807
- const { sourceCode } = context;
248808
- return {
248809
- checker: parserServices.program.getTypeChecker(),
248810
- esTreeNodeToTSNodeMap: parserServices.esTreeNodeToTSNodeMap,
248811
- parserServices,
248812
- program: sourceCode.ast,
248813
- sourceCode,
248814
- tsNodeToESTreeNodeMap: parserServices.tsNodeToESTreeNodeMap,
248815
- tsProgram: parserServices.program,
248816
- };
248817
- }
248818
-
248819
- const rule$A = createUntrackedRule({
249547
+ const rule$C = createUntrackedRule({
248820
249548
  create(context) {
248821
249549
  const { checker, esTreeNodeToTSNodeMap, program } = getTypeAwareRuleContext(context);
248822
249550
  const signalNodeMap = esTreeNodeToTSNodeMap;
@@ -248889,7 +249617,7 @@ const config$3 = {
248889
249617
  type: 'problem',
248890
249618
  },
248891
249619
  };
248892
- const rule$z = createRule({
249620
+ const rule$B = createRule({
248893
249621
  name: 'no-href-with-router-link',
248894
249622
  rule: config$3,
248895
249623
  });
@@ -248950,7 +249678,7 @@ function getScopeRoot(node) {
248950
249678
  return (findAncestor(node, (ancestor) => ancestor.type === dist$3.AST_NODE_TYPES.Program || isFunctionLike(ancestor)) ?? node);
248951
249679
  }
248952
249680
 
248953
- const rule$y = createRule({
249681
+ const rule$A = createRule({
248954
249682
  create(context) {
248955
249683
  const checkImplicitPublic = (node) => {
248956
249684
  const classRef = getEnclosingClass(node);
@@ -249012,7 +249740,7 @@ const rule$y = createRule({
249012
249740
  name: 'no-implicit-public',
249013
249741
  });
249014
249742
 
249015
- const rule$x = createRule({
249743
+ const rule$z = createRule({
249016
249744
  create(context) {
249017
249745
  const { sourceCode } = context;
249018
249746
  return {
@@ -249070,7 +249798,7 @@ function isInfiniteLoopLiteral(node) {
249070
249798
  function isInfiniteLoopTest(test) {
249071
249799
  return test === null || isInfiniteLoopLiteral(test);
249072
249800
  }
249073
- const rule$w = createRule({
249801
+ const rule$y = createRule({
249074
249802
  create(context) {
249075
249803
  return {
249076
249804
  DoWhileStatement(node) {
@@ -249115,7 +249843,7 @@ const rule$w = createRule({
249115
249843
  });
249116
249844
 
249117
249845
  const LEGACY_PEER_DEPS_PATTERN = /^legacy-peer-deps\s*=\s*true$/i;
249118
- const rule$v = createRule({
249846
+ const rule$x = createRule({
249119
249847
  create(context) {
249120
249848
  return {
249121
249849
  Program(node) {
@@ -249575,7 +250303,7 @@ const OBSOLETE_HTML_ATTRS = {
249575
250303
  };
249576
250304
 
249577
250305
  const MESSAGE_ID$9 = 'obsolete';
249578
- const rule$u = createRule({
250306
+ const rule$w = createRule({
249579
250307
  name: 'no-obsolete-attrs',
249580
250308
  rule: {
249581
250309
  create(context) {
@@ -249653,7 +250381,7 @@ const OBSOLETE_HTML_TAGS = new Set([
249653
250381
  ]);
249654
250382
 
249655
250383
  const MESSAGE_ID$8 = 'unexpected';
249656
- const rule$t = createRule({
250384
+ const rule$v = createRule({
249657
250385
  name: 'no-obsolete-tags',
249658
250386
  rule: {
249659
250387
  create(context) {
@@ -249680,7 +250408,7 @@ const rule$t = createRule({
249680
250408
  },
249681
250409
  });
249682
250410
 
249683
- const rule$s = createRule({
250411
+ const rule$u = createRule({
249684
250412
  create(context) {
249685
250413
  const { checker, esTreeNodeToTSNodeMap, sourceCode } = getTypeAwareRuleContext(context);
249686
250414
  return {
@@ -249824,7 +250552,7 @@ const config$2 = {
249824
250552
  type: 'problem',
249825
250553
  },
249826
250554
  };
249827
- const rule$r = createRule({
250555
+ const rule$t = createRule({
249828
250556
  name: 'no-project-as-in-ng-template',
249829
250557
  rule: config$2,
249830
250558
  });
@@ -249861,7 +250589,7 @@ function collectArrayExpressions(node) {
249861
250589
  }
249862
250590
  return result;
249863
250591
  }
249864
- const rule$q = createRule({
250592
+ const rule$s = createRule({
249865
250593
  create(context) {
249866
250594
  const { checker: typeChecker, esTreeNodeToTSNodeMap } = getTypeAwareRuleContext(context);
249867
250595
  const ignoreTupleContextualTyping = context.options[0]?.ignoreTupleContextualTyping ?? true;
@@ -249956,6 +250684,177 @@ const rule$q = createRule({
249956
250684
  name: 'no-redundant-type-annotation',
249957
250685
  });
249958
250686
 
250687
+ function isNullableCallType(call, checker, nodeMap) {
250688
+ try {
250689
+ const tsNode = nodeMap.get(call);
250690
+ if (!tsNode) {
250691
+ return false;
250692
+ }
250693
+ const type = checker.getTypeAtLocation(tsNode);
250694
+ if (!(type.flags & ts.TypeFlags.Union)) {
250695
+ return false;
250696
+ }
250697
+ return type.types.some((t) => !!(t.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)));
250698
+ }
250699
+ catch {
250700
+ return false;
250701
+ }
250702
+ }
250703
+ function getCalleeName(node) {
250704
+ const { callee } = node;
250705
+ if (callee.type === dist$3.AST_NODE_TYPES.MemberExpression &&
250706
+ !callee.computed &&
250707
+ callee.property.type === dist$3.AST_NODE_TYPES.Identifier) {
250708
+ return callee.property.name;
250709
+ }
250710
+ // Append 'Val' to avoid shadowing the signal variable itself (e.g. const xVal = x())
250711
+ if (callee.type === dist$3.AST_NODE_TYPES.Identifier) {
250712
+ return `${callee.name}Val`;
250713
+ }
250714
+ return 'value';
250715
+ }
250716
+ function findParentStatement(node) {
250717
+ for (let current = node; current.parent; current = current.parent) {
250718
+ if (isFunctionLike(current)) {
250719
+ return null;
250720
+ }
250721
+ if (current.parent.type === dist$3.AST_NODE_TYPES.BlockStatement ||
250722
+ current.parent.type === dist$3.AST_NODE_TYPES.Program) {
250723
+ return current;
250724
+ }
250725
+ }
250726
+ return null;
250727
+ }
250728
+ function findConciseArrowAncestor(node) {
250729
+ for (let current = node; current.parent; current = current.parent) {
250730
+ const { parent } = current;
250731
+ if (parent.type === dist$3.AST_NODE_TYPES.ArrowFunctionExpression &&
250732
+ parent.body.type !== dist$3.AST_NODE_TYPES.BlockStatement) {
250733
+ return parent;
250734
+ }
250735
+ if (isFunctionLike(parent)) {
250736
+ return null;
250737
+ }
250738
+ }
250739
+ return null;
250740
+ }
250741
+ function getArrowBodyIndent(arrowFn, sourceText) {
250742
+ const arrowStart = arrowFn.range[0];
250743
+ const lineStart = sourceText.lastIndexOf('\n', arrowStart - 1) + 1;
250744
+ const textBeforeArrow = sourceText.slice(lineStart, arrowStart);
250745
+ const outerIndent = /^(\s*)/.exec(textBeforeArrow)?.[1] ?? '';
250746
+ return { innerIndent: `${outerIndent} `, outerIndent };
250747
+ }
250748
+ function getStatementIndent(statement, sourceText) {
250749
+ const start = statement.range[0];
250750
+ const lineStart = sourceText.lastIndexOf('\n', start - 1) + 1;
250751
+ const before = sourceText.slice(lineStart, start);
250752
+ return /^\s*$/.test(before) ? before : '';
250753
+ }
250754
+ const rule$r = createRule({
250755
+ create(context) {
250756
+ const { checker, esTreeNodeToTSNodeMap, sourceCode } = getTypeAwareRuleContext(context);
250757
+ const signalNodeMap = esTreeNodeToTSNodeMap;
250758
+ function checkNode(node) {
250759
+ const callsByText = new Map();
250760
+ walkAst(node, (child) => {
250761
+ if (child === node) {
250762
+ return;
250763
+ }
250764
+ if (child.type === dist$3.AST_NODE_TYPES.ConditionalExpression ||
250765
+ child.type === dist$3.AST_NODE_TYPES.IfStatement ||
250766
+ isFunctionLike(child)) {
250767
+ return false;
250768
+ }
250769
+ if (child.type === dist$3.AST_NODE_TYPES.CallExpression &&
250770
+ isSignalReadCall(child, checker, signalNodeMap) &&
250771
+ isNullableCallType(child, checker, signalNodeMap)) {
250772
+ const text = sourceCode.getText(child);
250773
+ const list = callsByText.get(text) ?? [];
250774
+ list.push(child);
250775
+ callsByText.set(text, list);
250776
+ }
250777
+ return;
250778
+ });
250779
+ for (const [callText, calls] of callsByText) {
250780
+ if (calls.length < 2) {
250781
+ continue;
250782
+ }
250783
+ const firstCall = calls[0];
250784
+ if (!firstCall) {
250785
+ continue;
250786
+ }
250787
+ context.report({
250788
+ data: { call: callText },
250789
+ fix(fixer) {
250790
+ const varName = getCalleeName(firstCall);
250791
+ const parentStatement = findParentStatement(node);
250792
+ if (parentStatement) {
250793
+ const indent = getStatementIndent(parentStatement, sourceCode.text);
250794
+ const fixes = [
250795
+ fixer.insertTextBefore(parentStatement, `const ${varName} = ${callText};\n\n${indent}`),
250796
+ ];
250797
+ for (const call of calls) {
250798
+ const { parent } = call;
250799
+ const target = parent.type === dist$3.AST_NODE_TYPES.TSAsExpression
250800
+ ? parent
250801
+ : call;
250802
+ fixes.push(fixer.replaceText(target, varName));
250803
+ }
250804
+ return fixes;
250805
+ }
250806
+ const arrowFn = findConciseArrowAncestor(node);
250807
+ if (!arrowFn) {
250808
+ return null;
250809
+ }
250810
+ const arrowBody = arrowFn.body;
250811
+ const { innerIndent, outerIndent } = getArrowBodyIndent(arrowFn, sourceCode.text);
250812
+ const bodyText = sourceCode.getText(arrowBody);
250813
+ const bodyStart = arrowBody.range[0];
250814
+ const targets = calls
250815
+ .map((call) => {
250816
+ const { parent } = call;
250817
+ return parent.type === dist$3.AST_NODE_TYPES.TSAsExpression
250818
+ ? parent
250819
+ : call;
250820
+ })
250821
+ .sort((a, b) => a.range[0] - b.range[0]);
250822
+ let replacedBody = '';
250823
+ let lastIndex = 0;
250824
+ for (const target of targets) {
250825
+ const start = target.range[0] - bodyStart;
250826
+ const end = target.range[1] - bodyStart;
250827
+ replacedBody += `${bodyText.slice(lastIndex, start)}${varName}`;
250828
+ lastIndex = end;
250829
+ }
250830
+ replacedBody += bodyText.slice(lastIndex);
250831
+ const newBody = `{\n${innerIndent}const ${varName} = ${callText};\n\n${innerIndent}return ${replacedBody};\n${outerIndent}}`;
250832
+ return [fixer.replaceText(arrowBody, newBody)];
250833
+ },
250834
+ messageId: 'noRepeatedSignalInConditional',
250835
+ node: firstCall,
250836
+ });
250837
+ }
250838
+ }
250839
+ return {
250840
+ ConditionalExpression: checkNode,
250841
+ IfStatement: checkNode,
250842
+ };
250843
+ },
250844
+ meta: {
250845
+ docs: {
250846
+ description: 'Disallow reading the same nullable Angular signal more than once in a conditional (ternary or if) expression; extract it to a const variable instead',
250847
+ },
250848
+ fixable: 'code',
250849
+ messages: {
250850
+ noRepeatedSignalInConditional: 'Signal `{{call}}` is read multiple times in this conditional; extract it to a const variable',
250851
+ },
250852
+ schema: [],
250853
+ type: 'suggestion',
250854
+ },
250855
+ name: 'no-repeated-signal-in-conditional',
250856
+ });
250857
+
249959
250858
  /**
249960
250859
  * Strips TypeScript-only wrapper nodes that have no runtime meaning:
249961
250860
  * `as` casts, non-null assertions (`!`), type assertions (`<T>expr`), and
@@ -250286,7 +251185,7 @@ function inspectComputedBody(root, context, localScopes, visitedFunctions, repor
250286
251185
  return;
250287
251186
  });
250288
251187
  }
250289
- const rule$p = createRule({
251188
+ const rule$q = createRule({
250290
251189
  create(context) {
250291
251190
  const { checker, esTreeNodeToTSNodeMap, program, sourceCode, tsNodeToESTreeNodeMap, } = getTypeAwareRuleContext(context);
250292
251191
  const signalNodeMap = esTreeNodeToTSNodeMap;
@@ -250329,7 +251228,7 @@ const rule$p = createRule({
250329
251228
  name: 'no-side-effects-in-computed',
250330
251229
  });
250331
251230
 
250332
- const rule$o = createUntrackedRule({
251231
+ const rule$p = createUntrackedRule({
250333
251232
  create(context) {
250334
251233
  const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
250335
251234
  const signalNodeMap = esTreeNodeToTSNodeMap;
@@ -250423,7 +251322,7 @@ function templateContent(template, renderExpr) {
250423
251322
  : ''}`)
250424
251323
  .join('');
250425
251324
  }
250426
- const rule$n = createRule({
251325
+ const rule$o = createRule({
250427
251326
  create(context) {
250428
251327
  const { sourceCode } = context;
250429
251328
  let parserServices = null;
@@ -250758,7 +251657,7 @@ function buildReactiveCallReplacement(outerUntrackedCall, reactiveCall, sourceCo
250758
251657
  }
250759
251658
  return dedent(text, reactiveCall.loc.start.column - outerUntrackedCall.parent.loc.start.column);
250760
251659
  }
250761
- const rule$m = createUntrackedRule({
251660
+ const rule$n = createUntrackedRule({
250762
251661
  create(context) {
250763
251662
  const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
250764
251663
  const signalNodeMap = esTreeNodeToTSNodeMap;
@@ -250887,7 +251786,7 @@ function hasOpaqueSynchronousCalls(root, checker, esTreeNodeToTSNodeMap, program
250887
251786
  });
250888
251787
  return found;
250889
251788
  }
250890
- const rule$l = createUntrackedRule({
251789
+ const rule$m = createUntrackedRule({
250891
251790
  create(context) {
250892
251791
  const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
250893
251792
  const signalNodeMap = esTreeNodeToTSNodeMap;
@@ -250969,7 +251868,7 @@ const rule$l = createUntrackedRule({
250969
251868
  name: 'no-useless-untracked',
250970
251869
  });
250971
251870
 
250972
- const rule$k = createRule({
251871
+ const rule$l = createRule({
250973
251872
  create(context, [{ printWidth }]) {
250974
251873
  const sourceCode = context.sourceCode;
250975
251874
  const getLineEndIndex = (lineStartIndex) => {
@@ -251290,7 +252189,7 @@ function renderTest(node, sourceCode) {
251290
252189
  const text = sourceCode.getText(node);
251291
252190
  return needsParenthesesInOrChain(node) ? `(${text})` : text;
251292
252191
  }
251293
- const rule$j = createRule({
252192
+ const rule$k = createRule({
251294
252193
  create(context) {
251295
252194
  const { sourceCode } = context;
251296
252195
  function checkBody(statements) {
@@ -251393,7 +252292,7 @@ function getPushCall(node) {
251393
252292
  }
251394
252293
  return call;
251395
252294
  }
251396
- const rule$i = createRule({
252295
+ const rule$j = createRule({
251397
252296
  create(context) {
251398
252297
  const { sourceCode } = context;
251399
252298
  function checkBody(statements) {
@@ -251487,7 +252386,7 @@ function getModuleKeywordToken(sourceCode, node) {
251487
252386
  }
251488
252387
  return firstToken;
251489
252388
  }
251490
- const rule$h = createRule({
252389
+ const rule$i = createRule({
251491
252390
  create(context) {
251492
252391
  const { sourceCode } = context;
251493
252392
  return {
@@ -251757,7 +252656,7 @@ function collectSuspiciousReads(scope, checker, esTreeNodeToTSNodeMap, tsNodeToE
251757
252656
  });
251758
252657
  return [...suspicious.values()];
251759
252658
  }
251760
- const rule$g = createUntrackedRule({
252659
+ const rule$h = createUntrackedRule({
251761
252660
  create(context) {
251762
252661
  const { checker, esTreeNodeToTSNodeMap, program, sourceCode, tsNodeToESTreeNodeMap, } = getTypeAwareRuleContext(context);
251763
252662
  const signalNodeMap = esTreeNodeToTSNodeMap;
@@ -251845,7 +252744,7 @@ function getWrappedSignalGetter(node, checker, esTreeNodeToTSNodeMap) {
251845
252744
  }
251846
252745
  return isSignalType(getter, checker, esTreeNodeToTSNodeMap) ? body.callee : null;
251847
252746
  }
251848
- const rule$f = createUntrackedRule({
252747
+ const rule$g = createUntrackedRule({
251849
252748
  create(context) {
251850
252749
  const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
251851
252750
  const signalNodeMap = esTreeNodeToTSNodeMap;
@@ -251891,7 +252790,7 @@ const DOUBLE_QUOTE = '"';
251891
252790
  function isQuotableAttribute(attr) {
251892
252791
  return 'sourceSpan' in attr;
251893
252792
  }
251894
- const rule$e = createRule({
252793
+ const rule$f = createRule({
251895
252794
  name: 'quotes',
251896
252795
  rule: {
251897
252796
  create(context) {
@@ -251976,7 +252875,7 @@ const rule$e = createRule({
251976
252875
 
251977
252876
  const MESSAGE_ID$6 = 'missing';
251978
252877
  const DOCTYPE_REGEXP = /^\s*<!doctype html>/i;
251979
- const rule$d = createRule({
252878
+ const rule$e = createRule({
251980
252879
  name: 'require-doctype',
251981
252880
  rule: {
251982
252881
  create(context) {
@@ -252014,7 +252913,7 @@ function hasAlt(node) {
252014
252913
  return (node.attributes.some((attr) => attr.name === 'alt') ||
252015
252914
  node.inputs.some((input) => input.name === 'alt' || input.keySpan.details === 'attr.alt'));
252016
252915
  }
252017
- const rule$c = createRule({
252916
+ const rule$d = createRule({
252018
252917
  name: 'require-img-alt',
252019
252918
  rule: {
252020
252919
  create(context) {
@@ -252044,7 +252943,7 @@ const MESSAGE_IDS$1 = {
252044
252943
  EMPTY: 'empty',
252045
252944
  MISSING: 'missing',
252046
252945
  };
252047
- const rule$b = createRule({
252946
+ const rule$c = createRule({
252048
252947
  name: 'require-lang',
252049
252948
  rule: {
252050
252949
  create(context) {
@@ -252108,7 +253007,7 @@ function getClosestParentElement(node) {
252108
253007
  }
252109
253008
  return null;
252110
253009
  }
252111
- const rule$a = createRule({
253010
+ const rule$b = createRule({
252112
253011
  name: 'require-li-container',
252113
253012
  rule: {
252114
253013
  create(context) {
@@ -252156,7 +253055,7 @@ function hasMeaningfulTitleContent(node) {
252156
253055
  (typeof value === 'string' && value.trim().length > 0));
252157
253056
  });
252158
253057
  }
252159
- const rule$9 = createRule({
253058
+ const rule$a = createRule({
252160
253059
  name: 'require-title',
252161
253060
  rule: {
252162
253061
  create(context) {
@@ -252239,7 +253138,7 @@ const DEFAULT_EXCEPTIONS = [
252239
253138
  { from: 'TuiIslandDirective', to: 'TuiIsland' },
252240
253139
  { from: 'TuiTableBarsHostComponent', to: 'TuiTableBarsHost' },
252241
253140
  ];
252242
- const rule$8 = createRule({
253141
+ const rule$9 = createRule({
252243
253142
  create(context, [{ decorators = DEFAULT_DECORATORS, exceptions = DEFAULT_EXCEPTIONS }]) {
252244
253143
  const sourceCode = context.getSourceCode();
252245
253144
  const importedFromTaiga = {};
@@ -252395,17 +253294,6 @@ const rule$8 = createRule({
252395
253294
  name: 'short-tui-imports',
252396
253295
  });
252397
253296
 
252398
- function isFieldLikeMember(member) {
252399
- return (member.type === dist$3.AST_NODE_TYPES.PropertyDefinition ||
252400
- member.type === dist$3.AST_NODE_TYPES.TSAbstractPropertyDefinition);
252401
- }
252402
- function isAccessorMember(member) {
252403
- return (member.type === dist$3.AST_NODE_TYPES.MethodDefinition &&
252404
- (member.kind === 'get' || member.kind === 'set'));
252405
- }
252406
- function isRelevantSpacingClassMember(member) {
252407
- return isFieldLikeMember(member) || isAccessorMember(member);
252408
- }
252409
253297
  function isSingleLineNode(node) {
252410
253298
  return node.loc.start.line === node.loc.end.line;
252411
253299
  }
@@ -252447,12 +253335,26 @@ function getLeadingIndentation(text) {
252447
253335
  }
252448
253336
  return text.slice(0, index);
252449
253337
  }
253338
+ function getSpacingReplacement(sourceCode, betweenText, nextLine, blankLineCount) {
253339
+ const indentation = getLeadingIndentation(sourceCode.lines[nextLine - 1] ?? '');
253340
+ return `${getLineBreak(betweenText).repeat(blankLineCount + 1)}${indentation}`;
253341
+ }
252450
253342
 
252451
- const rule$7 = createRule({
253343
+ function isFieldLikeMember(member) {
253344
+ return (member.type === dist$3.AST_NODE_TYPES.PropertyDefinition ||
253345
+ member.type === dist$3.AST_NODE_TYPES.TSAbstractPropertyDefinition);
253346
+ }
253347
+ function isAccessorMember(member) {
253348
+ return (member.type === dist$3.AST_NODE_TYPES.MethodDefinition &&
253349
+ (member.kind === 'get' || member.kind === 'set'));
253350
+ }
253351
+ function isRelevantSpacingClassMember(member) {
253352
+ return isFieldLikeMember(member) || isAccessorMember(member);
253353
+ }
253354
+
253355
+ const rule$8 = createRule({
252452
253356
  create(context) {
252453
253357
  const sourceCode = context.sourceCode;
252454
- const getIndentation = (line) => getLeadingIndentation(sourceCode.lines[line - 1] ?? '');
252455
- const getSpacingReplacement = (betweenText, nextLine, blankLineCount) => `${getLineBreak(betweenText).repeat(blankLineCount + 1)}${getIndentation(nextLine)}`;
252456
253358
  return {
252457
253359
  ClassBody(node) {
252458
253360
  for (let index = 0; index < node.body.length - 1; index++) {
@@ -252477,7 +253379,7 @@ const rule$7 = createRule({
252477
253379
  isSingleLineNode(next) &&
252478
253380
  blankLineBetween) {
252479
253381
  context.report({
252480
- fix: (fixer) => fixer.replaceTextRange([current.range[1], next.range[0]], getSpacingReplacement(betweenText, next.loc.start.line, 0)),
253382
+ fix: (fixer) => fixer.replaceTextRange([current.range[1], next.range[0]], getSpacingReplacement(sourceCode, betweenText, next.loc.start.line, 0)),
252481
253383
  messageId: 'unexpectedBlankLineBeforeNextSingleLineField',
252482
253384
  node: next,
252483
253385
  });
@@ -252485,7 +253387,7 @@ const rule$7 = createRule({
252485
253387
  }
252486
253388
  if (needsSeparatedLine && !blankLineBetween) {
252487
253389
  context.report({
252488
- fix: (fixer) => fixer.replaceTextRange([current.range[1], next.range[0]], getSpacingReplacement(betweenText, next.loc.start.line, 1)),
253390
+ fix: (fixer) => fixer.replaceTextRange([current.range[1], next.range[0]], getSpacingReplacement(sourceCode, betweenText, next.loc.start.line, 1)),
252489
253391
  messageId: 'missingBlankLineAroundAccessor',
252490
253392
  node: next,
252491
253393
  });
@@ -252497,7 +253399,7 @@ const rule$7 = createRule({
252497
253399
  !isSingleLineNode(next) &&
252498
253400
  !blankLineBetween) {
252499
253401
  context.report({
252500
- fix: (fixer) => fixer.replaceTextRange([current.range[1], next.range[0]], getSpacingReplacement(betweenText, next.loc.start.line, 1)),
253402
+ fix: (fixer) => fixer.replaceTextRange([current.range[1], next.range[0]], getSpacingReplacement(sourceCode, betweenText, next.loc.start.line, 1)),
252501
253403
  messageId: 'missingBlankLineBeforeMultilineProperty',
252502
253404
  node: next,
252503
253405
  });
@@ -252508,7 +253410,7 @@ const rule$7 = createRule({
252508
253410
  !currentIsSingleLine &&
252509
253411
  !blankLineBetween) {
252510
253412
  context.report({
252511
- fix: (fixer) => fixer.replaceTextRange([current.range[1], next.range[0]], getSpacingReplacement(betweenText, next.loc.start.line, 1)),
253413
+ fix: (fixer) => fixer.replaceTextRange([current.range[1], next.range[0]], getSpacingReplacement(sourceCode, betweenText, next.loc.start.line, 1)),
252512
253414
  messageId: 'missingBlankLineAfterMultilineProperty',
252513
253415
  node: next,
252514
253416
  });
@@ -252534,6 +253436,151 @@ const rule$7 = createRule({
252534
253436
  name: 'single-line-class-property-spacing',
252535
253437
  });
252536
253438
 
253439
+ function getVariableSpacingStatement(node) {
253440
+ if (node.type === dist$3.AST_NODE_TYPES.VariableDeclaration) {
253441
+ return { declaration: node, exported: false, node };
253442
+ }
253443
+ if (node.type !== dist$3.AST_NODE_TYPES.ExportNamedDeclaration ||
253444
+ node.declaration?.type !== dist$3.AST_NODE_TYPES.VariableDeclaration) {
253445
+ return null;
253446
+ }
253447
+ return { declaration: node.declaration, exported: true, node };
253448
+ }
253449
+ function isRequireCall(node) {
253450
+ return (node.type === dist$3.AST_NODE_TYPES.CallExpression &&
253451
+ node.callee.type === dist$3.AST_NODE_TYPES.Identifier &&
253452
+ node.callee.name === 'require');
253453
+ }
253454
+ function isImportLikeInitializer(node) {
253455
+ const initializer = unwrapParenthesized(node);
253456
+ if (initializer.type === dist$3.AST_NODE_TYPES.ImportExpression ||
253457
+ isRequireCall(initializer)) {
253458
+ return true;
253459
+ }
253460
+ if (initializer.type === dist$3.AST_NODE_TYPES.AwaitExpression) {
253461
+ return isImportLikeInitializer(initializer.argument);
253462
+ }
253463
+ if (initializer.type === dist$3.AST_NODE_TYPES.ChainExpression) {
253464
+ return isImportLikeInitializer(initializer.expression);
253465
+ }
253466
+ if (initializer.type === dist$3.AST_NODE_TYPES.MemberExpression) {
253467
+ return isImportLikeInitializer(initializer.object);
253468
+ }
253469
+ if (initializer.type === dist$3.AST_NODE_TYPES.CallExpression) {
253470
+ return isImportLikeInitializer(initializer.callee);
253471
+ }
253472
+ return false;
253473
+ }
253474
+ function isImportLikeVariableDeclaration(declaration) {
253475
+ if (declaration.declarations.length !== 1) {
253476
+ return false;
253477
+ }
253478
+ const [declarator] = declaration.declarations;
253479
+ const init = declarator.init;
253480
+ if (!init) {
253481
+ return false;
253482
+ }
253483
+ return isImportLikeInitializer(init);
253484
+ }
253485
+ const rule$7 = createRule({
253486
+ create(context) {
253487
+ const sourceCode = context.sourceCode;
253488
+ const checkStatements = (statements) => {
253489
+ for (let index = 0; index < statements.length - 1; index++) {
253490
+ const currentStatement = statements[index];
253491
+ const nextStatement = statements[index + 1];
253492
+ if (!currentStatement || !nextStatement) {
253493
+ continue;
253494
+ }
253495
+ const current = getVariableSpacingStatement(currentStatement);
253496
+ const next = getVariableSpacingStatement(nextStatement);
253497
+ if (!current ||
253498
+ !next ||
253499
+ isImportLikeVariableDeclaration(current.declaration) ||
253500
+ isImportLikeVariableDeclaration(next.declaration)) {
253501
+ continue;
253502
+ }
253503
+ const betweenText = sourceCode.text.slice(current.node.range[1], next.node.range[0]);
253504
+ if (hasCommentLikeText(betweenText)) {
253505
+ continue;
253506
+ }
253507
+ const currentIsSingleLine = isSingleLineNode(current.node);
253508
+ const nextIsSingleLine = isSingleLineNode(next.node);
253509
+ const blankLineBetween = hasBlankLine(betweenText);
253510
+ const sameExportGroup = current.exported === next.exported;
253511
+ if (currentIsSingleLine &&
253512
+ nextIsSingleLine &&
253513
+ sameExportGroup &&
253514
+ blankLineBetween) {
253515
+ context.report({
253516
+ fix: (fixer) => fixer.replaceTextRange([current.node.range[1], next.node.range[0]], getSpacingReplacement(sourceCode, betweenText, next.node.loc.start.line, 0)),
253517
+ messageId: 'unexpectedBlankLineBeforeNextSingleLineVariable',
253518
+ node: next.node,
253519
+ });
253520
+ continue;
253521
+ }
253522
+ if (currentIsSingleLine &&
253523
+ nextIsSingleLine &&
253524
+ !sameExportGroup &&
253525
+ !blankLineBetween) {
253526
+ context.report({
253527
+ fix: (fixer) => fixer.replaceTextRange([current.node.range[1], next.node.range[0]], getSpacingReplacement(sourceCode, betweenText, next.node.loc.start.line, 1)),
253528
+ messageId: 'missingBlankLineBetweenVariableGroups',
253529
+ node: next.node,
253530
+ });
253531
+ }
253532
+ if (currentIsSingleLine && !nextIsSingleLine && !blankLineBetween) {
253533
+ context.report({
253534
+ fix: (fixer) => fixer.replaceTextRange([current.node.range[1], next.node.range[0]], getSpacingReplacement(sourceCode, betweenText, next.node.loc.start.line, 1)),
253535
+ messageId: 'missingBlankLineBeforeMultilineVariable',
253536
+ node: next.node,
253537
+ });
253538
+ continue;
253539
+ }
253540
+ if (!currentIsSingleLine && !blankLineBetween) {
253541
+ context.report({
253542
+ fix: (fixer) => fixer.replaceTextRange([current.node.range[1], next.node.range[0]], getSpacingReplacement(sourceCode, betweenText, next.node.loc.start.line, 1)),
253543
+ messageId: 'missingBlankLineAfterMultilineVariable',
253544
+ node: next.node,
253545
+ });
253546
+ }
253547
+ }
253548
+ };
253549
+ return {
253550
+ BlockStatement(node) {
253551
+ checkStatements(node.body);
253552
+ },
253553
+ Program(node) {
253554
+ checkStatements(node.body);
253555
+ },
253556
+ StaticBlock(node) {
253557
+ checkStatements(node.body);
253558
+ },
253559
+ SwitchCase(node) {
253560
+ checkStatements(node.consequent);
253561
+ },
253562
+ TSModuleBlock(node) {
253563
+ checkStatements(node.body);
253564
+ },
253565
+ };
253566
+ },
253567
+ meta: {
253568
+ docs: {
253569
+ description: 'Group consecutive single-line variable declarations together, while separating multiline variable declarations with blank lines',
253570
+ },
253571
+ fixable: 'code',
253572
+ messages: {
253573
+ missingBlankLineAfterMultilineVariable: 'Multiline variable declarations should be followed by a blank line before the next variable declaration',
253574
+ missingBlankLineBeforeMultilineVariable: 'Multiline variable declarations should be preceded by a blank line after single-line variable declarations',
253575
+ missingBlankLineBetweenVariableGroups: 'Exported and non-exported variable declarations should be separated by a blank line',
253576
+ unexpectedBlankLineBeforeNextSingleLineVariable: 'Single-line variable declarations should not be separated by a blank line before the next single-line variable declaration',
253577
+ },
253578
+ schema: [],
253579
+ type: 'layout',
253580
+ },
253581
+ name: 'single-line-variable-spacing',
253582
+ });
253583
+
252537
253584
  function getImportsArray(meta) {
252538
253585
  const property = meta.properties.find((literal) => literal.type === dist$2.AST_NODE_TYPES.Property &&
252539
253586
  literal.key.type === dist$2.AST_NODE_TYPES.Identifier &&
@@ -253545,52 +254592,55 @@ const plugin = {
253545
254592
  },
253546
254593
  rules: {
253547
254594
  'array-as-const': rule$5,
253548
- 'attrs-newline': rule$M,
254595
+ 'attrs-newline': rule$P,
253549
254596
  'class-property-naming': rule$4,
253550
- 'decorator-key-sort': rule$L,
253551
- 'element-newline': rule$K,
254597
+ 'decorator-key-sort': rule$O,
254598
+ 'element-newline': rule$N,
253552
254599
  'flat-exports': rule$3,
253553
- 'host-attributes-sort': rule$J,
253554
- 'html-logical-properties': rule$I,
253555
- 'injection-token-description': rule$H,
253556
- 'no-commonjs-import-patterns': rule$G,
253557
- 'no-deep-imports': rule$F,
253558
- 'no-deep-imports-to-indexed-packages': rule$E,
253559
- 'no-duplicate-attrs': rule$D,
253560
- 'no-duplicate-id': rule$C,
253561
- 'no-duplicate-in-head': rule$B,
253562
- 'no-fully-untracked-effect': rule$A,
253563
- 'no-href-with-router-link': rule$z,
253564
- 'no-implicit-public': rule$y,
253565
- 'no-import-assertions': rule$x,
253566
- 'no-infinite-loop': rule$w,
253567
- 'no-legacy-peer-deps': rule$v,
253568
- 'no-obsolete-attrs': rule$u,
253569
- 'no-obsolete-tags': rule$t,
253570
- 'no-playwright-empty-fill': rule$s,
253571
- 'no-project-as-in-ng-template': rule$r,
253572
- 'no-redundant-type-annotation': rule$q,
254600
+ 'host-attributes-sort': rule$M,
254601
+ 'html-logical-properties': rule$L,
254602
+ 'import-integrity': rule$K,
254603
+ 'injection-token-description': rule$J,
254604
+ 'no-commonjs-import-patterns': rule$I,
254605
+ 'no-deep-imports': rule$H,
254606
+ 'no-deep-imports-to-indexed-packages': rule$G,
254607
+ 'no-duplicate-attrs': rule$F,
254608
+ 'no-duplicate-id': rule$E,
254609
+ 'no-duplicate-in-head': rule$D,
254610
+ 'no-fully-untracked-effect': rule$C,
254611
+ 'no-href-with-router-link': rule$B,
254612
+ 'no-implicit-public': rule$A,
254613
+ 'no-import-assertions': rule$z,
254614
+ 'no-infinite-loop': rule$y,
254615
+ 'no-legacy-peer-deps': rule$x,
254616
+ 'no-obsolete-attrs': rule$w,
254617
+ 'no-obsolete-tags': rule$v,
254618
+ 'no-playwright-empty-fill': rule$u,
254619
+ 'no-project-as-in-ng-template': rule$t,
254620
+ 'no-redundant-type-annotation': rule$s,
254621
+ 'no-repeated-signal-in-conditional': rule$r,
253573
254622
  'no-restricted-attr-values': rule$2,
253574
- 'no-side-effects-in-computed': rule$p,
253575
- 'no-signal-reads-after-await-in-reactive-context': rule$o,
253576
- 'no-string-literal-concat': rule$n,
253577
- 'no-untracked-outside-reactive-context': rule$m,
253578
- 'no-useless-untracked': rule$l,
253579
- 'object-single-line': rule$k,
253580
- 'prefer-combined-if-control-flow': rule$j,
254623
+ 'no-side-effects-in-computed': rule$q,
254624
+ 'no-signal-reads-after-await-in-reactive-context': rule$p,
254625
+ 'no-string-literal-concat': rule$o,
254626
+ 'no-untracked-outside-reactive-context': rule$n,
254627
+ 'no-useless-untracked': rule$m,
254628
+ 'object-single-line': rule$l,
254629
+ 'prefer-combined-if-control-flow': rule$k,
253581
254630
  'prefer-deep-imports': rule$1,
253582
- 'prefer-multi-arg-push': rule$i,
253583
- 'prefer-namespace-keyword': rule$h,
253584
- 'prefer-untracked-incidental-signal-reads': rule$g,
253585
- 'prefer-untracked-signal-getter': rule$f,
253586
- quotes: rule$e,
253587
- 'require-doctype': rule$d,
253588
- 'require-img-alt': rule$c,
253589
- 'require-lang': rule$b,
253590
- 'require-li-container': rule$a,
253591
- 'require-title': rule$9,
253592
- 'short-tui-imports': rule$8,
253593
- 'single-line-class-property-spacing': rule$7,
254631
+ 'prefer-multi-arg-push': rule$j,
254632
+ 'prefer-namespace-keyword': rule$i,
254633
+ 'prefer-untracked-incidental-signal-reads': rule$h,
254634
+ 'prefer-untracked-signal-getter': rule$g,
254635
+ quotes: rule$f,
254636
+ 'require-doctype': rule$e,
254637
+ 'require-img-alt': rule$d,
254638
+ 'require-lang': rule$c,
254639
+ 'require-li-container': rule$b,
254640
+ 'require-title': rule$a,
254641
+ 'short-tui-imports': rule$9,
254642
+ 'single-line-class-property-spacing': rule$8,
254643
+ 'single-line-variable-spacing': rule$7,
253594
254644
  'standalone-imports-sort': rule$6,
253595
254645
  'strict-tui-doc-example': rule,
253596
254646
  },