eslint-plugin-th-rules 1.15.5 → 1.16.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/.yarn/releases/yarn-4.12.0.cjs +942 -0
- package/.yarnrc.yml +1 -1
- package/CHANGELOG.md +14 -0
- package/README.md +7 -10
- package/bun.lockb +0 -0
- package/docs/rules/top-level-functions.md +2 -3
- package/docs/rules/types-in-dts.md +112 -0
- package/package.json +3 -3
- package/src/index.js +1 -0
- package/src/rules/top-level-functions.js +45 -34
- package/src/rules/types-in-dts.js +95 -0
- package/.yarn/releases/yarn-4.6.0.cjs +0 -934
package/.yarnrc.yml
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [1.16.0](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v1.15.6...v1.16.0) (2026-01-05)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* add new rule 'types-in-dts' to enforce TypeScript type declarations in .d.ts files ([00c4769](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/00c4769f9a025642f7c72023df1dea82dbf33e72))
|
|
7
|
+
|
|
8
|
+
## [1.15.6](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v1.15.5...v1.15.6) (2024-12-30)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* enhance top-level functions rule to support async and export keywords ([cca9ceb](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/cca9cebe77fa01820048a55c444e55bd297b883c))
|
|
14
|
+
|
|
1
15
|
## [1.15.5](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v1.15.4...v1.15.5) (2024-12-30)
|
|
2
16
|
|
|
3
17
|
|
package/README.md
CHANGED
|
@@ -7,10 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
This repository contains custom ESLint rules to enhance code quality and consistency across projects.
|
|
9
9
|
|
|
10
|
-
# Custom ESLint Rules
|
|
11
|
-
|
|
12
|
-
This repository contains custom ESLint rules to enhance code quality and consistency across projects, created by Tomer Horowitz.
|
|
13
|
-
|
|
14
10
|
## Rules
|
|
15
11
|
<!-- begin auto-generated rules list -->
|
|
16
12
|
|
|
@@ -18,12 +14,13 @@ This repository contains custom ESLint rules to enhance code quality and consist
|
|
|
18
14
|
✅ Set in the `recommended` configuration.\
|
|
19
15
|
🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).
|
|
20
16
|
|
|
21
|
-
| Name | Description
|
|
22
|
-
| :------------------------------------------------------- |
|
|
23
|
-
| [no-comments](docs/rules/no-comments.md) | Disallow comments except for specified allowed patterns.
|
|
24
|
-
| [no-default-export](docs/rules/no-default-export.md) | Convert unnamed default exports to named default exports based on the file name.
|
|
25
|
-
| [no-destructuring](docs/rules/no-destructuring.md) | Disallow destructuring that does not meet certain conditions
|
|
26
|
-
| [top-level-functions](docs/rules/top-level-functions.md) | Require all top-level functions to be named/regular functions.
|
|
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
|
+
| [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][] | 🔧 |
|
|
23
|
+
| [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][] | |
|
|
27
24
|
|
|
28
25
|
<!-- end auto-generated rules list -->
|
|
29
26
|
|
package/bun.lockb
CHANGED
|
Binary file
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Require all top-level functions to be named/regular functions (`th-rules/top-level-functions`)
|
|
2
2
|
|
|
3
|
+
💼 This rule is enabled in the following configs: ✅ `recommended`, `recommended-react`, `recommended-typescript`.
|
|
4
|
+
|
|
3
5
|
🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
|
|
4
6
|
|
|
5
7
|
<!-- end auto-generated rule header -->
|
|
@@ -38,9 +40,6 @@ function myFunction() {
|
|
|
38
40
|
}
|
|
39
41
|
```
|
|
40
42
|
|
|
41
|
-
## Options
|
|
42
|
-
|
|
43
|
-
This rule has no options.
|
|
44
43
|
|
|
45
44
|
## When Not To Use It
|
|
46
45
|
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<pre>
|
|
2
|
+
# Require TypeScript type declarations (type/interface/enum) to be placed in .d.ts files (`th-rules/types-in-dts`)
|
|
3
|
+
|
|
4
|
+
💼 This rule is enabled in the following configs: ✅ `recommended`, `recommended-react`, `recommended-typescript`.
|
|
5
|
+
|
|
6
|
+
<!-- end auto-generated rule header -->
|
|
7
|
+
|
|
8
|
+
💼 This rule is enabled in the following configs: ✅ `recommended`, `recommended-react`, `recommended-typescript`.
|
|
9
|
+
|
|
10
|
+
<!-- end auto-generated rule header -->
|
|
11
|
+
|
|
12
|
+
This rule enforces a strict separation between **runtime code** and **type declarations** by requiring all top-level TypeScript type declarations to be defined in `.d.ts` files.
|
|
13
|
+
|
|
14
|
+
The rule applies to:
|
|
15
|
+
- `type` aliases
|
|
16
|
+
- `interface` declarations
|
|
17
|
+
- `enum` declarations
|
|
18
|
+
|
|
19
|
+
Any of these constructs declared outside of a `.d.ts` file will be reported, unless explicitly allowed via configuration.
|
|
20
|
+
|
|
21
|
+
## Rationale
|
|
22
|
+
|
|
23
|
+
Keeping type declarations in `.d.ts` files provides several benefits:
|
|
24
|
+
|
|
25
|
+
- Enforces a clean architectural boundary between runtime logic and type definitions
|
|
26
|
+
- Improves file readability by reducing noise in implementation files
|
|
27
|
+
- Encourages intentional, centralized ownership of public and shared types
|
|
28
|
+
- Prevents accidental runtime coupling with type-only constructs
|
|
29
|
+
- Aligns well with library-oriented or API-driven codebases
|
|
30
|
+
|
|
31
|
+
This rule is especially useful in large TypeScript projects, shared packages, or monorepos where type contracts are meant to be consumed independently of implementation.
|
|
32
|
+
|
|
33
|
+
## Examples
|
|
34
|
+
|
|
35
|
+
### ❌ Incorrect
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
// user.ts
|
|
39
|
+
type UserId = string;
|
|
40
|
+
|
|
41
|
+
interface User {
|
|
42
|
+
id: UserId;
|
|
43
|
+
name: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
enum Role {
|
|
47
|
+
Admin,
|
|
48
|
+
User,
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### ✅ Correct
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
// user.d.ts
|
|
56
|
+
type UserId = string;
|
|
57
|
+
|
|
58
|
+
interface User {
|
|
59
|
+
id: UserId;
|
|
60
|
+
name: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
enum Role {
|
|
64
|
+
Admin,
|
|
65
|
+
User,
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
// user.ts
|
|
71
|
+
import type { User, UserId, Role } from './user';
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Allowed usage
|
|
75
|
+
|
|
76
|
+
Using types, interfaces, or enums is always allowed in any file:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
function getUser(id: UserId): User {
|
|
80
|
+
// ...
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Options
|
|
85
|
+
|
|
86
|
+
<!-- begin auto-generated rule options list -->
|
|
87
|
+
|
|
88
|
+
| Name | Type |
|
|
89
|
+
| :------------- | :------ |
|
|
90
|
+
| `allowDeclare` | Boolean |
|
|
91
|
+
| `allowEnums` | Boolean |
|
|
92
|
+
|
|
93
|
+
<!-- end auto-generated rule options list -->
|
|
94
|
+
|
|
95
|
+
### `allowDeclare`
|
|
96
|
+
|
|
97
|
+
When set to `true`, the rule allows `declare` type declarations in non-`.d.ts` files.
|
|
98
|
+
|
|
99
|
+
This is useful when working with ambient declarations, global augmentations, or compatibility shims that must live alongside implementation code.
|
|
100
|
+
|
|
101
|
+
### `allowEnums`
|
|
102
|
+
|
|
103
|
+
When set to `true`, the rule allows `enum` declarations in non-`.d.ts` files.
|
|
104
|
+
|
|
105
|
+
This can be helpful in codebases that rely on runtime enums while still wanting to enforce `.d.ts` placement for interfaces and type aliases.
|
|
106
|
+
|
|
107
|
+
## Notes
|
|
108
|
+
|
|
109
|
+
- This rule does not enforce how types are imported or re-exported.
|
|
110
|
+
- It does not attempt to auto-fix violations, as moving declarations across files is not safe to do automatically.
|
|
111
|
+
- 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.
|
|
3
|
+
"version": "1.16.0",
|
|
4
4
|
"description": "A List of custom ESLint rules created by Tomer Horowitz",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"eslint-plugin-eslint-plugin": "^6.4.0",
|
|
50
50
|
"eslint-plugin-node": "^11.1.0",
|
|
51
51
|
"eslint-plugin-sonarjs": "^3.0.1",
|
|
52
|
-
"eslint-plugin-th-rules": "1.
|
|
52
|
+
"eslint-plugin-th-rules": "1.15.6",
|
|
53
53
|
"eslint-plugin-unicorn": "^56.0.1",
|
|
54
54
|
"mocha": "^11.0.1",
|
|
55
55
|
"npm-run-all": "^4.1.5",
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"typescript": "^5.7.2"
|
|
63
63
|
},
|
|
64
64
|
"license": "ISC",
|
|
65
|
-
"packageManager": "yarn@4.
|
|
65
|
+
"packageManager": "yarn@4.12.0"
|
|
66
66
|
}
|
package/src/index.js
CHANGED
|
@@ -19,6 +19,7 @@ const configs = {
|
|
|
19
19
|
'th-rules/no-default-export': 'error',
|
|
20
20
|
'th-rules/no-comments': 'error',
|
|
21
21
|
'th-rules/top-level-functions': 'error',
|
|
22
|
+
'th-rules/types-in-dts': 'error',
|
|
22
23
|
'unicorn/prefer-module': 'warn',
|
|
23
24
|
'unicorn/filename-case': 'off',
|
|
24
25
|
'unicorn/no-array-callback-reference': 'off',
|
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
/* eslint-disable unicorn/prefer-module */
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* @type {Object}
|
|
5
|
-
* @property {string} type - The type of the rule, in this case, 'suggestion'.
|
|
6
|
-
* @property {Object} docs - Documentation related to the rule.
|
|
7
|
-
* @property {string} docs.description - A brief description of the rule.
|
|
8
|
-
* @property {string} docs.category - The category of the rule, 'Stylistic Issues'.
|
|
9
|
-
* @property {boolean} docs.recommended - Indicates if the rule is recommended.
|
|
10
|
-
* @property {string} docs.url - The URL to the documentation of the rule.
|
|
11
|
-
* @property {string} fixable - Indicates if the rule is fixable, 'code'.
|
|
12
|
-
* @property {Array} schema - The schema for the rule options.
|
|
13
|
-
*/
|
|
14
3
|
const meta = {
|
|
15
4
|
type: 'suggestion',
|
|
16
5
|
docs: {
|
|
@@ -29,10 +18,13 @@ const meta = {
|
|
|
29
18
|
* @param {string} funcName - The name of the new function.
|
|
30
19
|
* @param {ArrowFunctionExpression} arrowNode - The ArrowFunctionExpression node.
|
|
31
20
|
* @param {import('eslint').SourceCode} sourceCode - The ESLint SourceCode object.
|
|
32
|
-
* @param {boolean} isExport - Whether or not this function is exported.
|
|
21
|
+
* @param {boolean} isExport - Whether or not this function is exported (e.g., `export const foo = ...`).
|
|
33
22
|
* @returns {string} The replacement code.
|
|
34
23
|
*/
|
|
35
24
|
function buildArrowFunctionReplacement(functionName, arrowNode, sourceCode, isExport) {
|
|
25
|
+
const asyncKeyword = arrowNode.async ? 'async ' : '';
|
|
26
|
+
const exportKeyword = isExport ? 'export ' : '';
|
|
27
|
+
|
|
36
28
|
const parametersText = arrowNode.params.map(parameter => sourceCode.getText(parameter)).join(', ');
|
|
37
29
|
|
|
38
30
|
let bodyText;
|
|
@@ -43,8 +35,7 @@ function buildArrowFunctionReplacement(functionName, arrowNode, sourceCode, isEx
|
|
|
43
35
|
bodyText = `{ return ${expressionText}; }`;
|
|
44
36
|
}
|
|
45
37
|
|
|
46
|
-
|
|
47
|
-
return `${exportKeyword}function ${functionName}(${parametersText}) ${bodyText}`;
|
|
38
|
+
return `${exportKeyword}${asyncKeyword}function ${functionName}(${parametersText}) ${bodyText}`;
|
|
48
39
|
}
|
|
49
40
|
|
|
50
41
|
/**
|
|
@@ -57,36 +48,40 @@ function buildArrowFunctionReplacement(functionName, arrowNode, sourceCode, isEx
|
|
|
57
48
|
* @returns {string} The replacement code.
|
|
58
49
|
*/
|
|
59
50
|
function buildFunctionExpressionReplacement(functionName, functionExprNode, sourceCode, isExport) {
|
|
51
|
+
const asyncKeyword = functionExprNode.async ? 'async ' : '';
|
|
52
|
+
const exportKeyword = isExport ? 'export ' : '';
|
|
53
|
+
|
|
60
54
|
const parametersText = functionExprNode.params.map(parameter => sourceCode.getText(parameter)).join(', ');
|
|
61
55
|
const bodyText = sourceCode.getText(functionExprNode.body);
|
|
62
56
|
|
|
63
|
-
|
|
64
|
-
return `${exportKeyword}function ${functionName}(${parametersText}) ${bodyText}`;
|
|
57
|
+
return `${exportKeyword}${asyncKeyword}function ${functionName}(${parametersText}) ${bodyText}`;
|
|
65
58
|
}
|
|
66
59
|
|
|
67
60
|
/**
|
|
68
|
-
* Build a replacement for an anonymous top-level FunctionDeclaration.
|
|
61
|
+
* Build a replacement for an anonymous top-level FunctionDeclaration (including async).
|
|
69
62
|
*
|
|
70
63
|
* @param {import('eslint').SourceCode} sourceCode
|
|
71
64
|
* @param {import('estree').FunctionDeclaration} node
|
|
72
65
|
* @param {string} [funcName='defaultFunction']
|
|
66
|
+
* @param {boolean} [isExport=false]
|
|
73
67
|
*/
|
|
74
|
-
function buildAnonymousFunctionDeclarationReplacement(sourceCode, node, functionName = 'defaultFunction') {
|
|
68
|
+
function buildAnonymousFunctionDeclarationReplacement(sourceCode, node, functionName = 'defaultFunction', isExport = false) {
|
|
75
69
|
const originalText = sourceCode.getText(node);
|
|
70
|
+
const exportKeyword = isExport ? 'export ' : '';
|
|
71
|
+
|
|
72
|
+
let replaced = originalText;
|
|
73
|
+
const asyncFunctionRegex = /^\s*async\s+function\s*\(/;
|
|
74
|
+
const functionRegex = /^\s*function\s*\(/;
|
|
75
|
+
|
|
76
|
+
replaced = asyncFunctionRegex.test(replaced) ? replaced.replace(asyncFunctionRegex, `async function ${functionName}(`) : replaced.replace(functionRegex, `function ${functionName}(`);
|
|
76
77
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return
|
|
78
|
+
if (isExport && !replaced.trimStart().startsWith('export')) {
|
|
79
|
+
replaced = `${exportKeyword}${replaced}`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return replaced;
|
|
82
83
|
}
|
|
83
84
|
|
|
84
|
-
/**
|
|
85
|
-
* ESLint rule to enforce naming conventions for top-level functions.
|
|
86
|
-
*
|
|
87
|
-
* @param {Object} context - The rule context provided by ESLint.
|
|
88
|
-
* @returns {Object} An object containing visitor methods for AST nodes.
|
|
89
|
-
*/
|
|
90
85
|
function create(context) {
|
|
91
86
|
const sourceCode = context.getSourceCode();
|
|
92
87
|
|
|
@@ -129,7 +124,10 @@ function create(context) {
|
|
|
129
124
|
isExport,
|
|
130
125
|
);
|
|
131
126
|
|
|
132
|
-
return fixer.replaceText(
|
|
127
|
+
return fixer.replaceText(
|
|
128
|
+
isExport ? grandParent : declParent,
|
|
129
|
+
replacement,
|
|
130
|
+
);
|
|
133
131
|
},
|
|
134
132
|
});
|
|
135
133
|
} else if (node.init.type === 'FunctionExpression') {
|
|
@@ -143,7 +141,10 @@ function create(context) {
|
|
|
143
141
|
sourceCode,
|
|
144
142
|
isExport,
|
|
145
143
|
);
|
|
146
|
-
return fixer.replaceText(
|
|
144
|
+
return fixer.replaceText(
|
|
145
|
+
isExport ? grandParent : declParent,
|
|
146
|
+
replacement,
|
|
147
|
+
);
|
|
147
148
|
},
|
|
148
149
|
});
|
|
149
150
|
}
|
|
@@ -156,7 +157,8 @@ function create(context) {
|
|
|
156
157
|
|
|
157
158
|
const parent = node.parent;
|
|
158
159
|
|
|
159
|
-
const isTopLevel
|
|
160
|
+
const isTopLevel
|
|
161
|
+
= parent.type === 'Program'
|
|
160
162
|
|| parent.type === 'ExportNamedDeclaration'
|
|
161
163
|
|| parent.type === 'ExportDefaultDeclaration';
|
|
162
164
|
|
|
@@ -164,15 +166,24 @@ function create(context) {
|
|
|
164
166
|
return;
|
|
165
167
|
}
|
|
166
168
|
|
|
169
|
+
const isExport
|
|
170
|
+
= parent.type === 'ExportNamedDeclaration'
|
|
171
|
+
|| parent.type === 'ExportDefaultDeclaration';
|
|
172
|
+
|
|
167
173
|
context.report({
|
|
168
174
|
node,
|
|
169
175
|
message: 'Top-level anonymous function declarations must be named.',
|
|
170
176
|
fix(fixer) {
|
|
171
177
|
const newName = 'defaultFunction';
|
|
172
|
-
const replacement = buildAnonymousFunctionDeclarationReplacement(
|
|
178
|
+
const replacement = buildAnonymousFunctionDeclarationReplacement(
|
|
179
|
+
sourceCode,
|
|
180
|
+
node,
|
|
181
|
+
newName,
|
|
182
|
+
isExport,
|
|
183
|
+
);
|
|
173
184
|
|
|
174
185
|
return fixer.replaceText(
|
|
175
|
-
|
|
186
|
+
isExport ? parent : node,
|
|
176
187
|
replacement,
|
|
177
188
|
);
|
|
178
189
|
},
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Enforce that TypeScript type declarations exist only in .d.ts files.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
type: 'problem',
|
|
7
|
+
docs: {
|
|
8
|
+
description: 'Require TypeScript type declarations (type/interface/enum) to be placed in .d.ts files',
|
|
9
|
+
category: 'Best Practices',
|
|
10
|
+
recommended: true,
|
|
11
|
+
url: 'https://github.com/tomerh2001/eslint-plugin-th-rules/blob/main/docs/rules/types-in-dts.md',
|
|
12
|
+
},
|
|
13
|
+
schema: [
|
|
14
|
+
{
|
|
15
|
+
type: 'object',
|
|
16
|
+
properties: {
|
|
17
|
+
allowEnums: {type: 'boolean'},
|
|
18
|
+
allowDeclare: {type: 'boolean'},
|
|
19
|
+
},
|
|
20
|
+
additionalProperties: false,
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
messages: {
|
|
24
|
+
moveToDts:
|
|
25
|
+
'Type declarations must be moved to a .d.ts file (for example "{{filename}}.d.ts").',
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {import('eslint').Rule.RuleContext} context
|
|
31
|
+
*/
|
|
32
|
+
function create(context) {
|
|
33
|
+
const options = context.options?.[0] ?? {};
|
|
34
|
+
const allowEnums = Boolean(options.allowEnums);
|
|
35
|
+
const allowDeclare = Boolean(options.allowDeclare);
|
|
36
|
+
|
|
37
|
+
function isDtsFile(filename) {
|
|
38
|
+
if (!filename || filename === '<input>') {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return filename.endsWith('.d.ts');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function hasDeclareModifier(node) {
|
|
46
|
+
if (node && node.declare === true) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const mods = node && Array.isArray(node.modifiers) ? node.modifiers : [];
|
|
51
|
+
return mods.some(m => m && m.type === 'TSDeclareKeyword');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function reportIfNotDts(node) {
|
|
55
|
+
const filename = context.getFilename();
|
|
56
|
+
if (isDtsFile(filename)) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (allowDeclare && hasDeclareModifier(node)) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
context.report({
|
|
65
|
+
node,
|
|
66
|
+
messageId: 'moveToDts',
|
|
67
|
+
data: {filename},
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
|
|
73
|
+
TSTypeAliasDeclaration(node) {
|
|
74
|
+
reportIfNotDts(node);
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
TSInterfaceDeclaration(node) {
|
|
78
|
+
reportIfNotDts(node);
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
TSEnumDeclaration(node) {
|
|
82
|
+
if (allowEnums) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
reportIfNotDts(node);
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module.exports = {
|
|
93
|
+
meta,
|
|
94
|
+
create,
|
|
95
|
+
};
|