@blumintinc/eslint-plugin-blumint 1.1.9 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -21,7 +21,8 @@ exports.default = (0, createRule_1.createRule)({
21
21
  defaultOptions: [],
22
22
  create(context) {
23
23
  // Check if the file is a TypeScript file
24
- const isTypeScript = context.getFilename().endsWith('.ts') || context.getFilename().endsWith('.tsx');
24
+ const isTypeScript = context.getFilename().endsWith('.ts') ||
25
+ context.getFilename().endsWith('.tsx');
25
26
  return {
26
27
  VariableDeclaration(node) {
27
28
  // Only check top-level const declarations
@@ -33,7 +34,7 @@ exports.default = (0, createRule_1.createRule)({
33
34
  return;
34
35
  }
35
36
  // Skip if any declaration is a function component, arrow function, forwardRef, or memo
36
- const shouldSkip = node.declarations.some(declaration => {
37
+ const shouldSkip = node.declarations.some((declaration) => {
37
38
  if (declaration.id.type !== utils_1.AST_NODE_TYPES.Identifier) {
38
39
  return false;
39
40
  }
@@ -44,7 +45,8 @@ exports.default = (0, createRule_1.createRule)({
44
45
  return false;
45
46
  }
46
47
  // Skip function components (uppercase name + arrow function)
47
- if (/^[A-Z]/.test(name) && init.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
48
+ if (/^[A-Z]/.test(name) &&
49
+ init.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
48
50
  return true;
49
51
  }
50
52
  // Skip any arrow function
@@ -84,26 +86,20 @@ exports.default = (0, createRule_1.createRule)({
84
86
  init.type === utils_1.AST_NODE_TYPES.NewExpression) {
85
87
  return;
86
88
  }
87
- // Check for UPPER_SNAKE_CASE
88
- if (!isUpperSnakeCase(name)) {
89
- context.report({
90
- node: declaration.id,
91
- messageId: 'upperSnakeCase',
92
- fix(fixer) {
93
- const newName = name
94
- .replace(/([A-Z])/g, '_$1')
95
- .toUpperCase()
96
- .replace(/^_/, '');
97
- return fixer.replaceText(declaration.id, newName);
98
- },
99
- });
100
- }
89
+ const sourceCode = context.getSourceCode();
90
+ const initText = sourceCode.getText(init);
91
+ const typeAnnotation = declaration.id.typeAnnotation;
92
+ const typeText = typeAnnotation
93
+ ? sourceCode.getText(typeAnnotation)
94
+ : '';
101
95
  // Only check for as const in TypeScript files
102
96
  if (isTypeScript) {
103
97
  const isAsConstExpression = (node) => {
104
98
  if (node.type === utils_1.AST_NODE_TYPES.TSAsExpression) {
105
- return (node.typeAnnotation?.type === utils_1.AST_NODE_TYPES.TSTypeReference &&
106
- node.typeAnnotation?.typeName?.name === 'const');
99
+ return (node.typeAnnotation?.type ===
100
+ utils_1.AST_NODE_TYPES.TSTypeReference &&
101
+ node.typeAnnotation?.typeName
102
+ ?.name === 'const');
107
103
  }
108
104
  return false;
109
105
  };
@@ -112,6 +108,15 @@ exports.default = (0, createRule_1.createRule)({
112
108
  if (isAsConstExpression(node)) {
113
109
  return false;
114
110
  }
111
+ // Handle type assertions
112
+ if (node.type === utils_1.AST_NODE_TYPES.TSTypeAssertion ||
113
+ node.type === utils_1.AST_NODE_TYPES.TSAsExpression) {
114
+ return shouldHaveAsConst(node.expression);
115
+ }
116
+ // Skip if there's an explicit type annotation
117
+ if (declaration.id.typeAnnotation) {
118
+ return false;
119
+ }
115
120
  // Check if it's a literal, array, or object that should have as const
116
121
  return (node.type === utils_1.AST_NODE_TYPES.Literal ||
117
122
  node.type === utils_1.AST_NODE_TYPES.ArrayExpression ||
@@ -119,16 +124,33 @@ exports.default = (0, createRule_1.createRule)({
119
124
  };
120
125
  if (shouldHaveAsConst(init)) {
121
126
  context.report({
122
- node: init,
127
+ node: declaration,
123
128
  messageId: 'asConst',
124
129
  fix(fixer) {
125
- const sourceCode = context.getSourceCode();
126
- const initText = sourceCode.getText(init);
127
130
  return fixer.replaceText(init, `${initText} as const`);
128
131
  },
129
132
  });
130
133
  }
131
134
  }
135
+ // Check for UPPER_SNAKE_CASE
136
+ if (!isUpperSnakeCase(name)) {
137
+ const newName = name
138
+ .replace(/([A-Z])/g, '_$1')
139
+ .toUpperCase()
140
+ .replace(/^_/, '');
141
+ context.report({
142
+ node: declaration,
143
+ messageId: 'upperSnakeCase',
144
+ fix(fixer) {
145
+ if (typeAnnotation) {
146
+ return fixer.replaceText(declaration, `${newName}${typeText} = ${initText}`);
147
+ }
148
+ else {
149
+ return fixer.replaceText(declaration.id, newName);
150
+ }
151
+ },
152
+ });
153
+ }
132
154
  });
133
155
  },
134
156
  };
@@ -0,0 +1 @@
1
+ export declare const noCompositingLayerProps: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"compositingLayer", [], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.noCompositingLayerProps = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ const createRule_1 = require("../utils/createRule");
6
+ // Convert camelCase to kebab-case
7
+ function toKebabCase(str) {
8
+ return str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
9
+ }
10
+ // Normalize property name to kebab-case for consistent lookup
11
+ function normalizePropertyName(name) {
12
+ // If already contains hyphens, assume it's kebab-case
13
+ if (name.includes('-'))
14
+ return name.toLowerCase();
15
+ // Convert camelCase to kebab-case
16
+ return toKebabCase(name).toLowerCase();
17
+ }
18
+ const COMPOSITING_PROPERTIES = new Set([
19
+ 'filter',
20
+ 'backdrop-filter',
21
+ 'will-change',
22
+ 'transform',
23
+ 'perspective',
24
+ 'backface-visibility',
25
+ 'contain',
26
+ 'mix-blend-mode',
27
+ 'opacity',
28
+ ]);
29
+ const COMPOSITING_VALUES = new Set([
30
+ 'translate3d',
31
+ 'scale3d',
32
+ 'translateZ',
33
+ 'transparent',
34
+ ]);
35
+ exports.noCompositingLayerProps = (0, createRule_1.createRule)({
36
+ name: 'no-compositing-layer-props',
37
+ meta: {
38
+ type: 'suggestion',
39
+ docs: {
40
+ description: 'Warn when using CSS properties that trigger compositing layers',
41
+ recommended: 'error',
42
+ },
43
+ schema: [],
44
+ messages: {
45
+ compositingLayer: '{{property}} may trigger a new compositing layer which can impact performance. Consider using alternative properties or add an eslint-disable comment if the layer promotion is intentional.',
46
+ },
47
+ },
48
+ defaultOptions: [],
49
+ create(context) {
50
+ const seenNodes = new WeakSet();
51
+ function checkPropertyValue(value) {
52
+ return (COMPOSITING_VALUES.has(value) ||
53
+ value.includes('translate3d') ||
54
+ value.includes('scale3d') ||
55
+ value.includes('translateZ'));
56
+ }
57
+ function checkProperty(propertyName, propertyValue) {
58
+ const normalizedName = normalizePropertyName(propertyName);
59
+ if (COMPOSITING_PROPERTIES.has(normalizedName)) {
60
+ // Special case for opacity - only warn if it's animated or fractional
61
+ if (normalizedName === 'opacity') {
62
+ if (!propertyValue)
63
+ return false;
64
+ const numValue = Number.parseFloat(propertyValue);
65
+ if (Number.isNaN(numValue))
66
+ return false;
67
+ return numValue > 0 && numValue < 1;
68
+ }
69
+ return true;
70
+ }
71
+ if (propertyValue && checkPropertyValue(propertyValue)) {
72
+ return true;
73
+ }
74
+ return false;
75
+ }
76
+ function isStyleContext(node) {
77
+ let current = node;
78
+ while (current?.parent) {
79
+ // Check for JSX style attribute
80
+ if (current.parent.type === utils_1.AST_NODE_TYPES.JSXAttribute &&
81
+ current.parent.name.type === utils_1.AST_NODE_TYPES.JSXIdentifier &&
82
+ current.parent.name.name === 'style') {
83
+ return true;
84
+ }
85
+ // Check for style-related variable names or properties
86
+ if (current.type === utils_1.AST_NODE_TYPES.VariableDeclarator &&
87
+ current.id.type === utils_1.AST_NODE_TYPES.Identifier &&
88
+ /style/i.test(current.id.name)) {
89
+ return true;
90
+ }
91
+ // Check for style-related object property assignments
92
+ if (current.parent.type === utils_1.AST_NODE_TYPES.Property &&
93
+ current.parent.key.type === utils_1.AST_NODE_TYPES.Identifier &&
94
+ /style/i.test(current.parent.key.name)) {
95
+ return true;
96
+ }
97
+ // Skip if we're in a TypeScript type definition
98
+ if (current.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration ||
99
+ current.type === utils_1.AST_NODE_TYPES.TSInterfaceDeclaration ||
100
+ current.type === utils_1.AST_NODE_TYPES.TSPropertySignature) {
101
+ return false;
102
+ }
103
+ current = current.parent;
104
+ }
105
+ return false;
106
+ }
107
+ function checkNode(node) {
108
+ // Skip if we've already processed this node
109
+ if (seenNodes.has(node))
110
+ return;
111
+ seenNodes.add(node);
112
+ // Skip if not in a style context
113
+ if (!isStyleContext(node))
114
+ return;
115
+ let propertyName = '';
116
+ let propertyValue = '';
117
+ // Get property name
118
+ if (node.key.type === utils_1.AST_NODE_TYPES.Identifier) {
119
+ propertyName = node.key.name;
120
+ }
121
+ else if (node.key.type === utils_1.AST_NODE_TYPES.Literal) {
122
+ propertyName = String(node.key.value);
123
+ }
124
+ // Get property value if it's a string literal or numeric literal
125
+ if (node.value.type === utils_1.AST_NODE_TYPES.Literal) {
126
+ propertyValue = String(node.value.value);
127
+ }
128
+ if (checkProperty(propertyName, propertyValue)) {
129
+ context.report({
130
+ node,
131
+ messageId: 'compositingLayer',
132
+ data: {
133
+ property: propertyName,
134
+ },
135
+ });
136
+ }
137
+ }
138
+ return {
139
+ // Handle object literal properties (inline styles)
140
+ Property(node) {
141
+ if (node.parent?.type !== utils_1.AST_NODE_TYPES.ObjectExpression)
142
+ return;
143
+ checkNode(node);
144
+ },
145
+ // Handle JSX style attributes
146
+ JSXAttribute(node) {
147
+ if (node.name.name !== 'style')
148
+ return;
149
+ if (node.value?.type === utils_1.AST_NODE_TYPES.JSXExpressionContainer &&
150
+ node.value.expression.type === utils_1.AST_NODE_TYPES.ObjectExpression) {
151
+ node.value.expression.properties.forEach((prop) => {
152
+ if (prop.type === utils_1.AST_NODE_TYPES.Property) {
153
+ checkNode(prop);
154
+ }
155
+ });
156
+ }
157
+ },
158
+ };
159
+ },
160
+ });
161
+ //# sourceMappingURL=no-compositing-layer-props.js.map
@@ -3,11 +3,41 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.noEntireObjectHookDeps = void 0;
4
4
  const utils_1 = require("@typescript-eslint/utils");
5
5
  const createRule_1 = require("../utils/createRule");
6
+ const typescript_1 = require("typescript");
6
7
  const HOOK_NAMES = new Set(['useEffect', 'useCallback', 'useMemo']);
7
8
  function isHookCall(node) {
8
9
  const callee = node.callee;
9
- return (callee.type === utils_1.AST_NODE_TYPES.Identifier &&
10
- HOOK_NAMES.has(callee.name));
10
+ return (callee.type === utils_1.AST_NODE_TYPES.Identifier && HOOK_NAMES.has(callee.name));
11
+ }
12
+ function isArrayOrPrimitive(checker, esTreeNode, nodeMap) {
13
+ const tsNode = nodeMap.get(esTreeNode);
14
+ if (!tsNode)
15
+ return false;
16
+ const type = checker.getTypeAtLocation(tsNode);
17
+ // Check if it's a primitive type
18
+ if (type.flags &
19
+ (typescript_1.TypeFlags.String |
20
+ typescript_1.TypeFlags.Number |
21
+ typescript_1.TypeFlags.Boolean |
22
+ typescript_1.TypeFlags.Null |
23
+ typescript_1.TypeFlags.Undefined |
24
+ typescript_1.TypeFlags.Void |
25
+ typescript_1.TypeFlags.Never |
26
+ typescript_1.TypeFlags.Any |
27
+ typescript_1.TypeFlags.Unknown |
28
+ typescript_1.TypeFlags.BigInt |
29
+ typescript_1.TypeFlags.ESSymbol)) {
30
+ return true;
31
+ }
32
+ // Check if it's an array type
33
+ const typeNode = checker.typeToTypeNode(type, undefined, undefined);
34
+ if (type.symbol?.name === 'Array' ||
35
+ type.symbol?.escapedName === 'Array' ||
36
+ (typeNode && ((0, typescript_1.isArrayTypeNode)(typeNode) || (0, typescript_1.isTupleTypeNode)(typeNode)))) {
37
+ return true;
38
+ }
39
+ // If it's not a primitive or array, and has properties, it's an object
40
+ return false;
11
41
  }
12
42
  function getObjectUsagesInHook(hookBody, objectName) {
13
43
  const usages = new Set();
@@ -25,75 +55,44 @@ function getObjectUsagesInHook(hookBody, objectName) {
25
55
  parts.unshift(current.property.name);
26
56
  current = current.object;
27
57
  }
28
- if (current.type === utils_1.AST_NODE_TYPES.Identifier && current.name === objectName) {
29
- parts.unshift(objectName);
58
+ if (current.type === utils_1.AST_NODE_TYPES.Identifier &&
59
+ current.name === objectName) {
30
60
  return parts.join('.');
31
61
  }
32
62
  return null;
33
63
  }
34
64
  function visit(node) {
35
- if (visited.has(node)) {
65
+ if (visited.has(node))
36
66
  return;
37
- }
38
67
  visited.add(node);
39
- if (node.type === utils_1.AST_NODE_TYPES.MemberExpression && !node.computed) {
40
- const accessPath = buildAccessPath(node);
41
- if (accessPath) {
42
- usages.add(accessPath);
68
+ if (node.type === utils_1.AST_NODE_TYPES.MemberExpression) {
69
+ const path = buildAccessPath(node);
70
+ if (path) {
71
+ usages.add(`${objectName}.${path}`);
43
72
  }
44
73
  }
45
- // Visit children
46
- switch (node.type) {
47
- case utils_1.AST_NODE_TYPES.BlockStatement:
48
- case utils_1.AST_NODE_TYPES.Program:
49
- node.body.forEach(child => visit(child));
50
- break;
51
- case utils_1.AST_NODE_TYPES.ExpressionStatement:
52
- visit(node.expression);
53
- break;
54
- case utils_1.AST_NODE_TYPES.CallExpression:
55
- visit(node.callee);
56
- node.arguments.forEach(arg => visit(arg));
57
- break;
58
- case utils_1.AST_NODE_TYPES.MemberExpression:
59
- visit(node.object);
60
- if (!node.computed) {
61
- visit(node.property);
62
- }
63
- break;
64
- case utils_1.AST_NODE_TYPES.ArrowFunctionExpression:
65
- case utils_1.AST_NODE_TYPES.FunctionExpression:
66
- if (node.body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
67
- visit(node.body);
68
- }
69
- else {
70
- visit(node.body);
74
+ // Visit all child nodes
75
+ for (const key in node) {
76
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
+ const child = node[key];
78
+ if (child && typeof child === 'object') {
79
+ if (Array.isArray(child)) {
80
+ child.forEach((item) => {
81
+ if (item && typeof item === 'object') {
82
+ visit(item);
83
+ }
84
+ });
71
85
  }
72
- break;
73
- case utils_1.AST_NODE_TYPES.ReturnStatement:
74
- if (node.argument) {
75
- visit(node.argument);
86
+ else if ('type' in child) {
87
+ visit(child);
76
88
  }
77
- break;
78
- case utils_1.AST_NODE_TYPES.ConditionalExpression:
79
- visit(node.test);
80
- visit(node.consequent);
81
- visit(node.alternate);
82
- break;
83
- case utils_1.AST_NODE_TYPES.LogicalExpression:
84
- case utils_1.AST_NODE_TYPES.BinaryExpression:
85
- visit(node.left);
86
- visit(node.right);
87
- break;
88
- case utils_1.AST_NODE_TYPES.TemplateLiteral:
89
- node.expressions.forEach(expr => visit(expr));
90
- break;
89
+ }
91
90
  }
92
91
  }
93
92
  visit(hookBody);
94
93
  // Filter out intermediate paths
95
94
  const paths = Array.from(usages);
96
- const filteredPaths = paths.filter(path => !paths.some(otherPath => otherPath !== path && otherPath.startsWith(path + '.')));
95
+ const filteredPaths = paths.filter((path) => !paths.some((otherPath) => otherPath !== path && otherPath.startsWith(path + '.')));
97
96
  return new Set(filteredPaths);
98
97
  }
99
98
  exports.noEntireObjectHookDeps = (0, createRule_1.createRule)({
@@ -112,6 +111,13 @@ exports.noEntireObjectHookDeps = (0, createRule_1.createRule)({
112
111
  },
113
112
  defaultOptions: [],
114
113
  create(context) {
114
+ const parserServices = context.parserServices;
115
+ // Check if we have access to TypeScript services
116
+ if (!parserServices?.program || !parserServices?.esTreeNodeToTSNodeMap) {
117
+ throw new Error('You have to enable the `project` setting in parser options to use this rule');
118
+ }
119
+ const checker = parserServices.program.getTypeChecker();
120
+ const nodeMap = parserServices.esTreeNodeToTSNodeMap;
115
121
  return {
116
122
  CallExpression(node) {
117
123
  if (!isHookCall(node)) {
@@ -119,8 +125,7 @@ exports.noEntireObjectHookDeps = (0, createRule_1.createRule)({
119
125
  }
120
126
  // Get the dependency array argument
121
127
  const depsArg = node.arguments[node.arguments.length - 1];
122
- if (!depsArg ||
123
- depsArg.type !== utils_1.AST_NODE_TYPES.ArrayExpression) {
128
+ if (!depsArg || depsArg.type !== utils_1.AST_NODE_TYPES.ArrayExpression) {
124
129
  return;
125
130
  }
126
131
  // Get the hook callback function
@@ -131,10 +136,13 @@ exports.noEntireObjectHookDeps = (0, createRule_1.createRule)({
131
136
  return;
132
137
  }
133
138
  // Check each dependency in the array
134
- depsArg.elements.forEach(element => {
135
- if (element &&
136
- element.type === utils_1.AST_NODE_TYPES.Identifier) {
139
+ depsArg.elements.forEach((element) => {
140
+ if (element && element.type === utils_1.AST_NODE_TYPES.Identifier) {
137
141
  const objectName = element.name;
142
+ // Skip if the dependency is an array or primitive type
143
+ if (isArrayOrPrimitive(checker, element, nodeMap)) {
144
+ return;
145
+ }
138
146
  const usages = getObjectUsagesInHook(callbackArg.body, objectName);
139
147
  // If we found specific field usages and the entire object is in deps
140
148
  if (usages.size > 0) {
@@ -25,16 +25,28 @@ exports.noUnusedProps = (0, createRule_1.createRule)({
25
25
  return {
26
26
  TSTypeAliasDeclaration(node) {
27
27
  if (node.id.name.endsWith('Props')) {
28
- if (node.typeAnnotation.type === utils_1.AST_NODE_TYPES.TSTypeLiteral) {
29
- const props = {};
30
- node.typeAnnotation.members.forEach((member) => {
31
- if (member.type === utils_1.AST_NODE_TYPES.TSPropertySignature &&
32
- member.key.type === utils_1.AST_NODE_TYPES.Identifier) {
33
- props[member.key.name] = member.key;
28
+ const props = {};
29
+ function extractProps(typeNode) {
30
+ if (typeNode.type === utils_1.AST_NODE_TYPES.TSTypeLiteral) {
31
+ typeNode.members.forEach((member) => {
32
+ if (member.type === utils_1.AST_NODE_TYPES.TSPropertySignature &&
33
+ member.key.type === utils_1.AST_NODE_TYPES.Identifier) {
34
+ props[member.key.name] = member.key;
35
+ }
36
+ });
37
+ }
38
+ else if (typeNode.type === utils_1.AST_NODE_TYPES.TSIntersectionType) {
39
+ typeNode.types.forEach(extractProps);
40
+ }
41
+ else if (typeNode.type === utils_1.AST_NODE_TYPES.TSTypeReference) {
42
+ // For referenced types like FormControlLabelProps, we need to track that these props should be forwarded
43
+ if (typeNode.typeName.type === utils_1.AST_NODE_TYPES.Identifier) {
44
+ props[`...${typeNode.typeName.name}`] = typeNode.typeName;
34
45
  }
35
- });
36
- propsTypes.set(node.id.name, props);
46
+ }
37
47
  }
48
+ extractProps(node.typeAnnotation);
49
+ propsTypes.set(node.id.name, props);
38
50
  }
39
51
  },
40
52
  VariableDeclaration(node) {
@@ -56,6 +68,19 @@ exports.noUnusedProps = (0, createRule_1.createRule)({
56
68
  prop.key.type === utils_1.AST_NODE_TYPES.Identifier) {
57
69
  used.add(prop.key.name);
58
70
  }
71
+ else if (prop.type === utils_1.AST_NODE_TYPES.RestElement &&
72
+ prop.argument.type === utils_1.AST_NODE_TYPES.Identifier) {
73
+ // Handle rest spread operator {...rest}
74
+ // When a rest operator is used, all remaining props are considered used
75
+ const propsType = propsTypes.get(typeName);
76
+ if (propsType) {
77
+ Object.keys(propsType).forEach((key) => {
78
+ if (key.startsWith('...')) {
79
+ used.add(key);
80
+ }
81
+ });
82
+ }
83
+ }
59
84
  });
60
85
  usedProps.set(typeName, used);
61
86
  }
@@ -35,7 +35,7 @@ exports.noUselessFragment = {
35
35
  type: 'suggestion',
36
36
  docs: {
37
37
  description: 'Prevent unnecessary use of React fragments',
38
- recommended: 'warn',
38
+ recommended: 'error',
39
39
  },
40
40
  messages: {
41
41
  noUselessFragment: 'React fragment is unnecessary when wrapping a single child',
@@ -28,7 +28,7 @@ exports.preferFragmentShorthand = {
28
28
  type: 'suggestion',
29
29
  docs: {
30
30
  description: 'Prefer <> shorthand for <React.Fragment>',
31
- recommended: 'warn',
31
+ recommended: 'error',
32
32
  },
33
33
  messages: {
34
34
  preferShorthand: 'Use <> shorthand for <React.Fragment>, unless a key is required for an iterator',
@@ -0,0 +1,11 @@
1
+ type MessageIds = 'tooManyParams' | 'sameTypeParams';
2
+ type Options = [
3
+ {
4
+ minimumParameters?: number;
5
+ checkSameTypeParameters?: boolean;
6
+ ignoreBoundMethods?: boolean;
7
+ ignoreVariadicFunctions?: boolean;
8
+ }
9
+ ];
10
+ export declare const preferSettingsObject: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<MessageIds, Options, import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
11
+ export {};