eslint-plugin-th-rules 1.17.0 → 1.18.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/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [1.18.0](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v1.17.1...v1.18.0) (2026-01-05)
2
+
3
+
4
+ ### Features
5
+
6
+ * add 'schemas-in-schemas-file' rule to enforce Zod schema declarations in dedicated files ([92b54a0](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/92b54a0b9ca4197c4e92c268d7d0cf0f8efc83cf))
7
+
8
+ ## [1.17.1](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v1.17.0...v1.17.1) (2026-01-05)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * improve style file validation messages and simplify code structure ([5c165b4](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/5c165b4fcbc103df752e7c56f988c725dae6a62c))
14
+
1
15
  # [1.17.0](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v1.16.0...v1.17.0) (2026-01-05)
2
16
 
3
17
 
package/README.md CHANGED
@@ -14,14 +14,15 @@ This repository contains custom ESLint rules to enhance code quality and consist
14
14
  ✅ Set in the `recommended` configuration.\
15
15
  🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).
16
16
 
17
- | Name                  | Description | 💼 | 🔧 |
18
- | :----------------------------------------------------------- | :---------------------------------------------------------------------------------------- | :--------------------------------------------------------------- | :- |
19
- | [no-comments](docs/rules/no-comments.md) | Disallow comments except for specified allowed patterns. | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | 🔧 |
20
- | [no-default-export](docs/rules/no-default-export.md) | Convert unnamed default exports to named default exports based on the file name. | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | 🔧 |
21
- | [no-destructuring](docs/rules/no-destructuring.md) | Disallow destructuring that does not meet certain conditions | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | |
22
- | [styles-in-styles-file](docs/rules/styles-in-styles-file.md) | Require React-Native StyleSheet.create(...) to be placed in a .styles.ts/.styles.tsx file | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | |
23
- | [top-level-functions](docs/rules/top-level-functions.md) | Require all top-level functions to be named/regular functions. | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | 🔧 |
24
- | [types-in-dts](docs/rules/types-in-dts.md) | Require TypeScript type declarations (type/interface/enum) to be placed in .d.ts files | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | |
17
+ | Name                    | Description | 💼 | 🔧 |
18
+ | :--------------------------------------------------------------- | :------------------------------------------------------------------------------------- | :--------------------------------------------------------------- | :- |
19
+ | [no-comments](docs/rules/no-comments.md) | Disallow comments except for specified allowed patterns. | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | 🔧 |
20
+ | [no-default-export](docs/rules/no-default-export.md) | Convert unnamed default exports to named default exports based on the file name. | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | 🔧 |
21
+ | [no-destructuring](docs/rules/no-destructuring.md) | Disallow destructuring that does not meet certain conditions | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | |
22
+ | [schemas-in-schemas-file](docs/rules/schemas-in-schemas-file.md) | Require Zod schema declarations to be placed in a .schemas.ts file | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | |
23
+ | [styles-in-styles-file](docs/rules/styles-in-styles-file.md) | Require React-Native StyleSheet.create(...) to be placed in a .styles.ts file | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | |
24
+ | [top-level-functions](docs/rules/top-level-functions.md) | Require all top-level functions to be named/regular functions. | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | 🔧 |
25
+ | [types-in-dts](docs/rules/types-in-dts.md) | Require TypeScript type declarations (type/interface/enum) to be placed in .d.ts files | ✅ ![badge-recommended-react][] ![badge-recommended-typescript][] | |
25
26
 
26
27
  <!-- end auto-generated rules list -->
27
28
 
@@ -0,0 +1,168 @@
1
+ # Require Zod schema declarations to be placed in a .schemas.ts file (`th-rules/schemas-in-schemas-file`)
2
+
3
+ 💼 This rule is enabled in the following configs: ✅ `recommended`, `recommended-react`, `recommended-typescript`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ 💼 This rule is enabled in the following configs: ✅ `recommended`, `recommended-react`, `recommended-typescript`.
8
+
9
+ &lt;!-- end auto-generated rule header --&gt;
10
+
11
+ This rule enforces that Zod schema **declarations** are defined in dedicated schema files (by default: `.schemas.ts` / `.schemas.tsx`), rather than inside implementation/component files.
12
+
13
+ The intent is to keep business logic and UI code focused, while consolidating validation/contract definitions into a predictable location.
14
+
15
+ ## Rationale
16
+
17
+ Keeping Zod schemas in dedicated files:
18
+ - reduces noise in implementation files (especially components and services),
19
+ - encourages reuse of validation contracts across the codebase,
20
+ - improves review quality by keeping diffs focused (schema changes vs logic changes),
21
+ - standardizes file layout in larger projects and monorepos.
22
+
23
+ ## What the rule reports
24
+
25
+ The rule reports Zod “schema builder” calls (e.g. `z.object(...)`, `z.string()`, `z.enum(...)`, `z.coerce.number()`, etc.) in files that do **not** match one of the allowed suffixes.
26
+
27
+ By default, it identifies Zod usage by tracking imports from `'zod'` (e.g. `import { z } from 'zod'`, `import { z as zod } from 'zod'`, `import * as zod from 'zod'`).
28
+
29
+ ## Examples
30
+
31
+ ### ❌ Incorrect
32
+
33
+ ```ts
34
+ // ArticleCard.tsx
35
+ import {z} from 'zod';
36
+
37
+ const articleSchema = z.object({
38
+ id: z.string(),
39
+ title: z.string().min(1),
40
+ });
41
+ ```
42
+
43
+ ```ts
44
+ // user.ts
45
+ import {z as zod} from 'zod';
46
+
47
+ export const userSchema = zod.object({
48
+ email: zod.string().email(),
49
+ });
50
+ ```
51
+
52
+ ### ✅ Correct
53
+
54
+ ```ts
55
+ // ArticleCard.schemas.ts
56
+ import {z} from 'zod';
57
+
58
+ export const articleSchema = z.object({
59
+ id: z.string(),
60
+ title: z.string().min(1),
61
+ });
62
+ ```
63
+
64
+ ```ts
65
+ // ArticleCard.tsx
66
+ import {articleSchema} from './ArticleCard.schemas';
67
+
68
+ export function ArticleCard() {
69
+ // articleSchema is used here (validation, inference, etc.)
70
+ return null;
71
+ }
72
+ ```
73
+
74
+ ### Allowed usage (always allowed)
75
+
76
+ Using schemas and type inference is allowed anywhere:
77
+
78
+ ```ts
79
+ import type {z} from 'zod';
80
+ import {articleSchema} from './ArticleCard.schemas';
81
+
82
+ export type Article = z.infer&lt;typeof articleSchema&gt;;
83
+ ```
84
+
85
+ ## Options
86
+
87
+ &lt;!-- begin auto-generated rule options list --&gt;
88
+
89
+ | Name | Type |
90
+ | :----------------- | :------- |
91
+ | `allowedSuffixes` | String[] |
92
+ | `allowInTests` | Boolean |
93
+ | `onlyWhenAssigned` | Boolean |
94
+
95
+ &lt;!-- end auto-generated rule options list --&gt;
96
+
97
+ ### `allowedSuffixes`
98
+
99
+ An array of filename suffixes that are allowed to contain Zod schema declarations.
100
+
101
+ Default:
102
+ - `.schemas.ts`
103
+ - `.schemas.tsx`
104
+
105
+ Example:
106
+
107
+ ```json
108
+ {
109
+ "rules": {
110
+ "th-rules/schemas-in-schemas-file": ["error", {
111
+ "allowedSuffixes": [".schemas.ts", ".schemas.tsx", ".validation.ts"]
112
+ }]
113
+ }
114
+ }
115
+ ```
116
+
117
+ ### `allowInTests`
118
+
119
+ When set to `true`, the rule allows Zod schema declarations in common test file patterns (e.g. `*.test.ts`, `*.spec.ts`, `*.test.tsx`, `*.spec.tsx`).
120
+
121
+ Default: `false`
122
+
123
+ Example:
124
+
125
+ ```json
126
+ {
127
+ "rules": {
128
+ "th-rules/schemas-in-schemas-file": ["error", {
129
+ "allowInTests": true
130
+ }]
131
+ }
132
+ }
133
+ ```
134
+
135
+ ### `onlyWhenAssigned`
136
+
137
+ When set to `true`, the rule reports only Zod schema builder calls that are assigned to a variable (or assigned via `=`), for example:
138
+
139
+ ```ts
140
+ const userSchema = z.object({ ... });
141
+ userSchema = z.object({ ... });
142
+ ```
143
+
144
+ If set to `false` (default), the rule reports any Zod schema builder call found in a non-allowed file, including inline schemas:
145
+
146
+ ```ts
147
+ foo(z.object({ ... }));
148
+ ```
149
+
150
+ Default: `false`
151
+
152
+ Example:
153
+
154
+ ```json
155
+ {
156
+ "rules": {
157
+ "th-rules/schemas-in-schemas-file": ["error", {
158
+ "onlyWhenAssigned": true
159
+ }]
160
+ }
161
+ }
162
+ ```
163
+
164
+ ## Notes
165
+
166
+ - This rule is filename-based; it enforces a convention rather than performing semantic analysis.
167
+ - The rule does not auto-fix, as moving schemas across files safely (and updating imports) is not generally safe to automate.
168
+ - If you define Zod builders through wrappers (e.g. `createSchema(...)` that internally calls Zod), this rule will not detect those unless extended to match your helper patterns.
@@ -1,11 +1,10 @@
1
- <pre>
2
- # Require React-Native StyleSheet.create(...) to be placed in a .styles.ts/.styles.tsx file (`th-rules/styles-in-styles-file`)
1
+ # Require React-Native StyleSheet.create(...) to be placed in a .styles.ts file (`th-rules/styles-in-styles-file`)
3
2
 
4
3
  💼 This rule is enabled in the following configs: ✅ `recommended`, `recommended-react`, `recommended-typescript`.
5
4
 
6
5
  <!-- end auto-generated rule header -->
7
6
 
8
- This rule enforces that React-Native stylesheet declarations created via `StyleSheet.create(...)` live in a dedicated styles file, typically ending with `.styles.ts` or `.styles.tsx`.
7
+ This rule enforces that React-Native stylesheet declarations created via `StyleSheet.create(...)` live in a dedicated styles file, typically ending with `.styles.ts`.
9
8
 
10
9
  In practice, this prevents implementation/component files from containing large style objects, and encourages consistent separation of concerns.
11
10
 
@@ -19,7 +18,7 @@ Keeping styles in dedicated files:
19
18
 
20
19
  ## What the rule reports
21
20
 
22
- The rule reports any `StyleSheet.create(...)` call in files whose names do **not** match one of the allowed suffixes (by default, `.styles.ts` and `.styles.tsx`).
21
+ The rule reports any `StyleSheet.create(...)` call in files whose names do **not** match one of the allowed suffixes (by default, `.styles.ts`).
23
22
 
24
23
  Optionally, it can also report `StyleSheet.compose(...)` calls.
25
24
 
@@ -100,7 +99,6 @@ An array of filename suffixes that are allowed to contain `StyleSheet.create(...
100
99
 
101
100
  Default:
102
101
  - `.styles.ts`
103
- - `.styles.tsx`
104
102
 
105
103
  Example:
106
104
 
@@ -108,7 +106,7 @@ Example:
108
106
  {
109
107
  "rules": {
110
108
  "th-rules/styles-in-styles-file": ["error", {
111
- "allowedSuffixes": [".styles.ts", ".styles.tsx", ".native-styles.ts"]
109
+ "allowedSuffixes": [".styles.ts", ".native-styles.ts"]
112
110
  }]
113
111
  }
114
112
  }
@@ -139,4 +137,3 @@ Example:
139
137
  - other styling systems (e.g., styled-components, Tamagui, Emotion),
140
138
  - calls to other `StyleSheet.*` helpers (e.g., `flatten`, `hairlineWidth`).
141
139
  - The rule is filename-based. If ESLint is invoked with `<input>` (stdin), the rule will treat it as not being an allowed styles file.
142
- </pre>
@@ -1,4 +1,3 @@
1
- <pre>
2
1
  # Require TypeScript type declarations (type/interface/enum) to be placed in .d.ts files (`th-rules/types-in-dts`)
3
2
 
4
3
  💼 This rule is enabled in the following configs: ✅ `recommended`, `recommended-react`, `recommended-typescript`.
@@ -109,4 +108,3 @@ This can be helpful in codebases that rely on runtime enums while still wanting
109
108
  - This rule does not enforce how types are imported or re-exported.
110
109
  - It does not attempt to auto-fix violations, as moving declarations across files is not safe to do automatically.
111
110
  - The rule operates purely at the syntax level and does not require type information.
112
- </pre>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-th-rules",
3
- "version": "1.17.0",
3
+ "version": "1.18.0",
4
4
  "description": "A List of custom ESLint rules created by Tomer Horowitz",
5
5
  "keywords": [
6
6
  "eslint",
package/src/index.js CHANGED
@@ -20,6 +20,7 @@ const configs = {
20
20
  'th-rules/no-comments': 'error',
21
21
  'th-rules/top-level-functions': 'error',
22
22
  'th-rules/styles-in-styles-file': 'error',
23
+ 'th-rules/schemas-in-schemas-file': 'error',
23
24
  'th-rules/types-in-dts': 'error',
24
25
  'unicorn/prefer-module': 'warn',
25
26
  'unicorn/filename-case': 'off',
@@ -0,0 +1,191 @@
1
+ const meta = {
2
+ type: 'problem',
3
+ docs: {
4
+ description: 'Require Zod schema declarations to be placed in a .schemas.ts file',
5
+ category: 'Stylistic Issues',
6
+ recommended: false,
7
+ url: 'https://github.com/tomerh2001/eslint-plugin-th-rules/blob/main/docs/rules/schemas-in-schemas-file.md',
8
+ },
9
+ schema: [
10
+ {
11
+ type: 'object',
12
+ properties: {
13
+ allowedSuffixes: {
14
+ type: 'array',
15
+ items: {type: 'string', minLength: 1},
16
+ minItems: 1,
17
+ },
18
+ /**
19
+ * If true, only report when the Zod call is assigned to a variable
20
+ * (e.g. const userSchema = z.object(...)).
21
+ * If false, report any Zod schema-building call expression.
22
+ */
23
+ onlyWhenAssigned: {type: 'boolean'},
24
+
25
+ /**
26
+ * If true, allow Zod calls inside *.test.* / *.spec.* files.
27
+ */
28
+ allowInTests: {type: 'boolean'},
29
+ },
30
+ additionalProperties: false,
31
+ },
32
+ ],
33
+ messages: {
34
+ moveSchema:
35
+ 'Zod schemas must be defined in a dedicated schemas file ({{suffixes}}).',
36
+ },
37
+ };
38
+
39
+ function create(context) {
40
+ const options = context.options?.[0] ?? {};
41
+ const allowedSuffixes = options.allowedSuffixes ?? ['.schemas.ts'];
42
+ const onlyWhenAssigned = Boolean(options.onlyWhenAssigned);
43
+ const allowInTests = Boolean(options.allowInTests);
44
+
45
+ /** @type {Set<string>} */
46
+ const zodIdentifiers = new Set();
47
+
48
+ function filenameAllowed(filename) {
49
+ if (!filename || filename === '<input>') {
50
+ return false;
51
+ }
52
+
53
+ if (allowInTests
54
+ && /\.(test|spec)\.[jt]sx?$/.test(filename)) {
55
+ return true;
56
+ }
57
+
58
+ return allowedSuffixes.some(suffix => filename.endsWith(suffix));
59
+ }
60
+
61
+ function isZodModuleImport(node) {
62
+ return node?.source?.type === 'Literal' && node.source.value === 'zod';
63
+ }
64
+
65
+ function collectZodIdentifiersFromImport(node) {
66
+ if (!isZodModuleImport(node)) {
67
+ return;
68
+ }
69
+
70
+ for (const spec of node.specifiers ?? []) {
71
+ if (spec.type === 'ImportSpecifier') {
72
+ const imported = spec.imported;
73
+ const local = spec.local;
74
+
75
+ if (imported?.type === 'Identifier' && imported.name === 'z' && local?.type === 'Identifier') {
76
+ zodIdentifiers.add(local.name);
77
+ }
78
+ }
79
+
80
+ if (spec.type === 'ImportNamespaceSpecifier' && spec.local?.type === 'Identifier') {
81
+ zodIdentifiers.add(spec.local.name);
82
+ }
83
+ }
84
+ }
85
+
86
+ function isZodBuilderCall(node) {
87
+ const callee = node?.callee;
88
+ if (!callee || callee.type !== 'MemberExpression') {
89
+ return false;
90
+ }
91
+
92
+ if (callee.computed) {
93
+ return false;
94
+ }
95
+
96
+ const object = callee.object;
97
+ const property = callee.property;
98
+
99
+ if (object?.type !== 'Identifier') {
100
+ return false;
101
+ }
102
+
103
+ if (!zodIdentifiers.has(object.name)) {
104
+ return false;
105
+ }
106
+
107
+ return property?.type === 'Identifier';
108
+ }
109
+
110
+ function isZodChainedBuilderCall(node) {
111
+ const callee = node?.callee;
112
+ if (!callee || callee.type !== 'MemberExpression') {
113
+ return false;
114
+ }
115
+
116
+ if (callee.computed) {
117
+ return false;
118
+ }
119
+
120
+ let current = callee.object;
121
+ while (current && current.type === 'MemberExpression' && !current.computed) {
122
+ current = current.object;
123
+ }
124
+
125
+ return current?.type === 'Identifier' && zodIdentifiers.has(current.name);
126
+ }
127
+
128
+ function getAssignmentTargetName(callNode) {
129
+ const p = callNode.parent;
130
+
131
+ if (p?.type === 'VariableDeclarator') {
132
+ if (p.id?.type === 'Identifier') {
133
+ return p.id.name;
134
+ }
135
+
136
+ return null;
137
+ }
138
+
139
+ if (p?.type === 'AssignmentExpression') {
140
+ if (p.left?.type === 'Identifier') {
141
+ return p.left.name;
142
+ }
143
+
144
+ return null;
145
+ }
146
+
147
+ return null;
148
+ }
149
+
150
+ function report(node) {
151
+ const filename = context.getFilename();
152
+ if (filenameAllowed(filename)) {
153
+ return;
154
+ }
155
+
156
+ const targetName = getAssignmentTargetName(node);
157
+ if (onlyWhenAssigned && !targetName) {
158
+ return;
159
+ }
160
+
161
+ const target = targetName ? ` "${targetName}"` : '';
162
+
163
+ context.report({
164
+ node,
165
+ messageId: 'moveSchema',
166
+ data: {
167
+ filename,
168
+ suffixes: allowedSuffixes.join(' or '),
169
+ target,
170
+ },
171
+ });
172
+ }
173
+
174
+ return {
175
+ ImportDeclaration(node) {
176
+ collectZodIdentifiersFromImport(node);
177
+ },
178
+
179
+ CallExpression(node) {
180
+ if (zodIdentifiers.size === 0) {
181
+ return;
182
+ }
183
+
184
+ if (isZodBuilderCall(node) || isZodChainedBuilderCall(node)) {
185
+ report(node);
186
+ }
187
+ },
188
+ };
189
+ }
190
+
191
+ module.exports = {meta, create};
@@ -1,7 +1,7 @@
1
1
  const meta = {
2
2
  type: 'problem',
3
3
  docs: {
4
- description: 'Require React-Native StyleSheet.create(...) to be placed in a .styles.ts/.styles.tsx file',
4
+ description: 'Require React-Native StyleSheet.create(...) to be placed in a .styles.ts file',
5
5
  category: 'Stylistic Issues',
6
6
  recommended: false,
7
7
  url: 'https://github.com/tomerh2001/eslint-plugin-th-rules/blob/main/docs/rules/styles-in-styles-file.md',
@@ -10,19 +10,11 @@ const meta = {
10
10
  {
11
11
  type: 'object',
12
12
  properties: {
13
- /**
14
- * Allowed style file suffixes. Defaults:
15
- * [".styles.ts", ".styles.tsx"]
16
- */
17
13
  allowedSuffixes: {
18
14
  type: 'array',
19
15
  items: {type: 'string', minLength: 1},
20
16
  minItems: 1,
21
17
  },
22
-
23
- /**
24
- * If true, also flag `StyleSheet.compose(...)` (optional).
25
- */
26
18
  includeCompose: {type: 'boolean'},
27
19
  },
28
20
  additionalProperties: false,
@@ -30,13 +22,13 @@ const meta = {
30
22
  ],
31
23
  messages: {
32
24
  moveStyles:
33
- 'React-Native styles must be moved to a .styles.ts/.styles.tsx file (for example "{{filename}}.styles.ts").',
25
+ 'React-Native styles must be defined in a dedicated styles file ({{suffixes}}).',
34
26
  },
35
27
  };
36
28
 
37
29
  function create(context) {
38
30
  const options = context.options?.[0] ?? {};
39
- const allowedSuffixes = options.allowedSuffixes ?? ['.styles.ts', '.styles.tsx'];
31
+ const allowedSuffixes = options.allowedSuffixes ?? ['.styles.ts'];
40
32
  const includeCompose = Boolean(options.includeCompose);
41
33
 
42
34
  function isAllowedStyleFile(filename) {
@@ -56,18 +48,62 @@ function create(context) {
56
48
  const object = callee.object;
57
49
  const property = callee.property;
58
50
 
59
- const isStyleSheet
60
- = object
61
- && object.type === 'Identifier'
62
- && object.name === 'StyleSheet';
51
+ return (
52
+ object?.type === 'Identifier'
53
+ && object.name === 'StyleSheet'
54
+ && !callee.computed
55
+ && property?.type === 'Identifier'
56
+ && property.name === memberName
57
+ );
58
+ }
59
+
60
+ /**
61
+ * Try to infer the “name” of the style object, e.g.:
62
+ * const styles = StyleSheet.create(...) -> "styles"
63
+ * styles = StyleSheet.create(...) -> "styles"
64
+ * exports.styles = StyleSheet.create(...) -> "exports.styles"
65
+ */
66
+ function getAssignmentTargetName(callNode) {
67
+ const p = callNode.parent;
68
+
69
+ if (p?.type === 'VariableDeclarator') {
70
+ const id = p.id;
71
+ if (id?.type === 'Identifier') {
72
+ return id.name;
73
+ }
74
+
75
+ return null;
76
+ }
77
+
78
+ if (p?.type === 'AssignmentExpression') {
79
+ const left = p.left;
80
+
81
+ if (left?.type === 'Identifier') {
82
+ return left.name;
83
+ }
84
+
85
+ if (left?.type === 'MemberExpression' && !left.computed) {
86
+ const object = left.object;
87
+ const property = left.property;
88
+
89
+ const objectName
90
+ = object?.type === 'Identifier'
91
+ ? object.name
92
+ : (object?.type === 'ThisExpression'
93
+ ? 'this'
94
+ : null);
63
95
 
64
- const isMember
65
- = !callee.computed
66
- && property
67
- && property.type === 'Identifier'
68
- && property.name === memberName;
96
+ const propertyName = property?.type === 'Identifier' ? property.name : null;
97
+
98
+ if (objectName && propertyName) {
99
+ return `${objectName}.${propertyName}`;
100
+ }
101
+ }
69
102
 
70
- return isStyleSheet && isMember;
103
+ return null;
104
+ }
105
+
106
+ return null;
71
107
  }
72
108
 
73
109
  function report(node) {
@@ -76,12 +112,16 @@ function create(context) {
76
112
  return;
77
113
  }
78
114
 
115
+ const targetName = getAssignmentTargetName(node);
116
+ const target = targetName ? ` "${targetName}"` : '';
117
+
79
118
  context.report({
80
119
  node,
81
120
  messageId: 'moveStyles',
82
121
  data: {
83
122
  filename,
84
123
  suffixes: allowedSuffixes.join(' or '),
124
+ target,
85
125
  },
86
126
  });
87
127
  }
@@ -100,7 +140,4 @@ function create(context) {
100
140
  };
101
141
  }
102
142
 
103
- module.exports = {
104
- meta,
105
- create,
106
- };
143
+ module.exports = {meta, create};
@@ -22,7 +22,7 @@ const meta = {
22
22
  ],
23
23
  messages: {
24
24
  moveToDts:
25
- 'Type declarations must be moved to a .d.ts file (for example "{{filename}}.d.ts").',
25
+ 'Type declarations must be moved to a .d.ts file.',
26
26
  },
27
27
  };
28
28