@rotki/eslint-plugin 0.6.1 → 1.0.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/README.md +35 -5
- package/dist/index.mjs +192 -298
- package/package.json +23 -24
- package/dist/index.cjs +0 -813
- package/dist/index.d.cts +0 -108
package/README.md
CHANGED
|
@@ -1,15 +1,45 @@
|
|
|
1
1
|
# @rotki/eslint-plugin
|
|
2
2
|
|
|
3
|
-
rotki
|
|
3
|
+
[](https://www.npmjs.com/package/@rotki/eslint-plugin)
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
and [vuetifyjs/eslint-plugin-vuetify](https://github.com/vuetifyjs/eslint-plugin-vuetify).
|
|
5
|
+
An ESLint plugin for rotki projects that provides custom rules and configurations to maintain consistent code quality.
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
This ESLint plugin is designed specifically for rotki projects, drawing inspiration from established plugins like:
|
|
10
|
+
|
|
11
|
+
- [intlify/eslint-plugin-vue-i18n](https://github.com/intlify/eslint-plugin-vue-i18n)
|
|
12
|
+
- [vuetifyjs/eslint-plugin-vuetify](https://github.com/vuetifyjs/eslint-plugin-vuetify)
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Using pnpm (recommended)
|
|
18
|
+
pnpm add -D @rotki/eslint-plugin
|
|
19
|
+
|
|
20
|
+
# Using npm
|
|
21
|
+
npm install --save-dev @rotki/eslint-plugin
|
|
22
|
+
|
|
23
|
+
# Using yarn
|
|
24
|
+
yarn add -D @rotki/eslint-plugin
|
|
25
|
+
```
|
|
9
26
|
|
|
10
27
|
## Documentation
|
|
11
28
|
|
|
12
|
-
|
|
29
|
+
For detailed usage instructions, available rules, and configuration options,
|
|
30
|
+
please visit our [documentation](https://rotki.github.io/eslint-plugin).
|
|
31
|
+
|
|
32
|
+
## Contributing
|
|
33
|
+
|
|
34
|
+
Contributions are welcome!
|
|
35
|
+
Please read our [Contributing Guide](./CONTRIBUTING.md) before submitting a Pull Request.
|
|
36
|
+
The guide includes detailed information about:
|
|
37
|
+
|
|
38
|
+
- Project prerequisites
|
|
39
|
+
- Development setup
|
|
40
|
+
- Commit message conventions
|
|
41
|
+
- Code style and linting
|
|
42
|
+
- Pull request process
|
|
13
43
|
|
|
14
44
|
## License
|
|
15
45
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,117 +1,12 @@
|
|
|
1
|
+
import { TSESTree } from '@typescript-eslint/utils';
|
|
1
2
|
import createDebug from 'debug';
|
|
2
|
-
import { extname } from 'node:path';
|
|
3
3
|
import * as compat from 'eslint-compat-utils';
|
|
4
|
+
import { extname } from 'node:path';
|
|
4
5
|
import { pascalCase, kebabCase } from 'scule';
|
|
5
|
-
import { TSESTree } from '@typescript-eslint/utils';
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
const version = "0.6.1";
|
|
9
|
-
const packageManager = "pnpm@9.15.0";
|
|
10
|
-
const type = "module";
|
|
11
|
-
const license = "AGPL-3.0";
|
|
12
|
-
const bugs = {
|
|
13
|
-
url: "https://github.com/rotki/eslint-plugin/issues"
|
|
14
|
-
};
|
|
15
|
-
const repository = {
|
|
16
|
-
type: "git",
|
|
17
|
-
url: "https://github.com/rotki/eslint-plugin.git"
|
|
18
|
-
};
|
|
19
|
-
const author = "Rotki Solutions GmbH <info@rotki.com>";
|
|
20
|
-
const files = [
|
|
21
|
-
"dist"
|
|
22
|
-
];
|
|
23
|
-
const main = "./dist/index.mjs";
|
|
24
|
-
const module = "./dist/index.mjs";
|
|
25
|
-
const types = "./dist/index.d.ts";
|
|
26
|
-
const exports = {
|
|
27
|
-
".": {
|
|
28
|
-
types: "./dist/index.d.ts",
|
|
29
|
-
require: "./dist/index.cjs",
|
|
30
|
-
"import": "./dist/index.mjs"
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
const sideEffects = false;
|
|
34
|
-
const scripts = {
|
|
35
|
-
clean: "rimraf .nyc_output coverage dist docs/.vitepress/dist",
|
|
36
|
-
coverage: "nyc report --reporter lcov && opener coverage/lcov-report/index.html",
|
|
37
|
-
generate: "node --experimental-specifier-resolution=node --loader ts-node/esm scripts/update-rule-docs.ts",
|
|
38
|
-
"generate:index": "node --experimental-specifier-resolution=node --loader ts-node/esm scripts/update-docs-index.ts",
|
|
39
|
-
lint: "eslint .",
|
|
40
|
-
"lint:fix": "eslint . --fix",
|
|
41
|
-
build: "unbuild",
|
|
42
|
-
dev: "unbuild --stub",
|
|
43
|
-
prepublishOnly: "pnpm run build",
|
|
44
|
-
test: "vitest",
|
|
45
|
-
"test:coverage": "vitest run --coverage",
|
|
46
|
-
"new": "node --experimental-specifier-resolution=node --loader ts-node/esm ./scripts/new-rule.ts",
|
|
47
|
-
docs: "vitepress dev docs",
|
|
48
|
-
"docs:build": "pnpm run generate && pnpm run generate:index && vitepress build docs",
|
|
49
|
-
prepare: "husky",
|
|
50
|
-
typecheck: "tsc --noEmit",
|
|
51
|
-
release: "bumpp -r --no-push"
|
|
52
|
-
};
|
|
53
|
-
const peerDependencies = {
|
|
54
|
-
eslint: "^9.0.0"
|
|
55
|
-
};
|
|
56
|
-
const dependencies = {
|
|
57
|
-
"@typescript-eslint/utils": "8.18.0",
|
|
58
|
-
debug: "4.4.0",
|
|
59
|
-
"eslint-compat-utils": "0.6.4",
|
|
60
|
-
"jsonc-eslint-parser": "2.4.0",
|
|
61
|
-
scule: "1.3.0",
|
|
62
|
-
"vue-eslint-parser": "9.4.3",
|
|
63
|
-
"yaml-eslint-parser": "1.2.3"
|
|
64
|
-
};
|
|
65
|
-
const devDependencies = {
|
|
66
|
-
"@commitlint/cli": "19.6.0",
|
|
67
|
-
"@commitlint/config-conventional": "19.6.0",
|
|
68
|
-
"@rotki/eslint-config": "3.6.0",
|
|
69
|
-
"@types/debug": "4.1.12",
|
|
70
|
-
"@types/node": "20",
|
|
71
|
-
"@typescript-eslint/eslint-plugin": "8.18.0",
|
|
72
|
-
"@typescript-eslint/parser": "8.18.0",
|
|
73
|
-
"@typescript-eslint/rule-tester": "8.18.0",
|
|
74
|
-
"@vitest/coverage-v8": "2.1.8",
|
|
75
|
-
bumpp: "9.9.0",
|
|
76
|
-
debug: "4.4.0",
|
|
77
|
-
eslint: "9.16.0",
|
|
78
|
-
husky: "9.1.7",
|
|
79
|
-
"lint-staged": "15.2.11",
|
|
80
|
-
rimraf: "6.0.1",
|
|
81
|
-
"ts-node": "10.9.2",
|
|
82
|
-
typescript: "5.7.2",
|
|
83
|
-
unbuild: "2.0.0",
|
|
84
|
-
vitepress: "1.5.0",
|
|
85
|
-
vitest: "2.1.8"
|
|
86
|
-
};
|
|
87
|
-
const engines = {
|
|
88
|
-
node: ">=20",
|
|
89
|
-
pnpm: ">=9 <10"
|
|
90
|
-
};
|
|
7
|
+
const version = "1.0.0";
|
|
91
8
|
const pkg = {
|
|
92
|
-
|
|
93
|
-
version: version,
|
|
94
|
-
packageManager: packageManager,
|
|
95
|
-
type: type,
|
|
96
|
-
license: license,
|
|
97
|
-
bugs: bugs,
|
|
98
|
-
repository: repository,
|
|
99
|
-
author: author,
|
|
100
|
-
files: files,
|
|
101
|
-
main: main,
|
|
102
|
-
module: module,
|
|
103
|
-
types: types,
|
|
104
|
-
exports: exports,
|
|
105
|
-
sideEffects: sideEffects,
|
|
106
|
-
scripts: scripts,
|
|
107
|
-
peerDependencies: peerDependencies,
|
|
108
|
-
dependencies: dependencies,
|
|
109
|
-
devDependencies: devDependencies,
|
|
110
|
-
engines: engines,
|
|
111
|
-
"lint-staged": {
|
|
112
|
-
"*.{js,cjs,ts,vue,yml,json,md}": "eslint"
|
|
113
|
-
}
|
|
114
|
-
};
|
|
9
|
+
version: version};
|
|
115
10
|
|
|
116
11
|
function getFilename(context) {
|
|
117
12
|
return compat.getFilename(context);
|
|
@@ -120,6 +15,63 @@ function getSourceCode(context) {
|
|
|
120
15
|
return compat.getSourceCode(context);
|
|
121
16
|
}
|
|
122
17
|
|
|
18
|
+
function createRecommended(plugin, name, flat) {
|
|
19
|
+
const rules = Object.fromEntries(Object.entries(plugin.rules).filter(([_key, rule]) => rule.meta.recommended === "recommended" && !rule.meta.deprecated).map(([key]) => [`${name}/${key}`, 2]));
|
|
20
|
+
if (flat) {
|
|
21
|
+
return {
|
|
22
|
+
plugins: {
|
|
23
|
+
[name]: plugin
|
|
24
|
+
},
|
|
25
|
+
rules
|
|
26
|
+
};
|
|
27
|
+
} else {
|
|
28
|
+
return {
|
|
29
|
+
plugins: [name],
|
|
30
|
+
rules
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getStringLiteralValue(node, stringOnly = false) {
|
|
36
|
+
if (node.type === "Literal") {
|
|
37
|
+
if (node.value == null) {
|
|
38
|
+
if (!stringOnly && node.bigint != null)
|
|
39
|
+
return node.bigint;
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
if (typeof node.value === "string")
|
|
43
|
+
return node.value;
|
|
44
|
+
if (!stringOnly)
|
|
45
|
+
return String(node.value);
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
if (node.type === "TemplateLiteral" && node.expressions.length === 0 && node.quasis.length === 1) {
|
|
49
|
+
return node.quasis[0].value.cooked;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
function getStaticPropertyName(node) {
|
|
54
|
+
if (node.type === "Property" || node.type === "MethodDefinition") {
|
|
55
|
+
if (!node.computed) {
|
|
56
|
+
const key2 = node.key;
|
|
57
|
+
if (key2.type === "Identifier")
|
|
58
|
+
return key2.name;
|
|
59
|
+
}
|
|
60
|
+
const key = node.key;
|
|
61
|
+
return getStringLiteralValue(key);
|
|
62
|
+
} else if (node.type === "MemberExpression") {
|
|
63
|
+
if (!node.computed) {
|
|
64
|
+
const property2 = node.property;
|
|
65
|
+
if (property2.type === "Identifier")
|
|
66
|
+
return property2.name;
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
const property = node.property;
|
|
70
|
+
return getStringLiteralValue(property);
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
123
75
|
const blobUrl = "https://rotki.github.io/eslint-plugin/rules/";
|
|
124
76
|
function RuleCreator(urlCreator) {
|
|
125
77
|
return function createNamedRule({
|
|
@@ -182,65 +134,107 @@ function defineTemplateBodyVisitor(context, templateBodyVisitor, scriptVisitor,
|
|
|
182
134
|
);
|
|
183
135
|
}
|
|
184
136
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
if (
|
|
199
|
-
return
|
|
137
|
+
const debug$3 = createDebug("@rotki/eslint-plugin:consistent-ref-type-annotation");
|
|
138
|
+
const RULE_NAME$5 = "consistent-ref-type-annotation";
|
|
139
|
+
const FIXABLE_METHODS = ["ref", "computed"];
|
|
140
|
+
function checkAssignmentDeclaration(context, node, declaration, options) {
|
|
141
|
+
const source = getSourceCode(context);
|
|
142
|
+
const { allowInference } = options;
|
|
143
|
+
let declarationTypeArguments;
|
|
144
|
+
const init = declaration.init;
|
|
145
|
+
if (!(init && init.type === TSESTree.AST_NODE_TYPES.CallExpression))
|
|
146
|
+
return;
|
|
147
|
+
const callee = init.callee;
|
|
148
|
+
if (!(callee && callee.type === TSESTree.AST_NODE_TYPES.Identifier))
|
|
149
|
+
return;
|
|
150
|
+
if (!Array.prototype.includes.call(FIXABLE_METHODS, callee.name))
|
|
151
|
+
return;
|
|
152
|
+
const name = callee.name;
|
|
153
|
+
debug$3(`found ${name}, checking type arguments`);
|
|
154
|
+
const initializationTypeArguments = init.typeArguments;
|
|
155
|
+
const typeAnnotation = declaration.id.typeAnnotation;
|
|
156
|
+
if (typeAnnotation) {
|
|
157
|
+
const typeNode = typeAnnotation.typeAnnotation;
|
|
158
|
+
if (typeNode && typeNode.type === TSESTree.AST_NODE_TYPES.TSTypeReference)
|
|
159
|
+
declarationTypeArguments = typeNode.typeArguments;
|
|
200
160
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (
|
|
205
|
-
if (
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
if (property2.type === "Identifier")
|
|
216
|
-
return property2.name;
|
|
217
|
-
return null;
|
|
161
|
+
if (initializationTypeArguments && !declarationTypeArguments)
|
|
162
|
+
return;
|
|
163
|
+
debug$3(`generating report for ${name}`);
|
|
164
|
+
if (!initializationTypeArguments && !declarationTypeArguments) {
|
|
165
|
+
if (allowInference) {
|
|
166
|
+
debug$3("type inference is allowed");
|
|
167
|
+
} else {
|
|
168
|
+
context.report({
|
|
169
|
+
data: {
|
|
170
|
+
name
|
|
171
|
+
},
|
|
172
|
+
messageId: "missingType",
|
|
173
|
+
node
|
|
174
|
+
});
|
|
218
175
|
}
|
|
219
|
-
|
|
220
|
-
return getStringLiteralValue(property);
|
|
176
|
+
return;
|
|
221
177
|
}
|
|
222
|
-
|
|
178
|
+
context.report({
|
|
179
|
+
data: {
|
|
180
|
+
name
|
|
181
|
+
},
|
|
182
|
+
fix(fixer) {
|
|
183
|
+
const fixes = [];
|
|
184
|
+
if (!initializationTypeArguments && callee)
|
|
185
|
+
fixes.push(fixer.insertTextAfter(callee, source.getText(declarationTypeArguments)));
|
|
186
|
+
if (typeAnnotation)
|
|
187
|
+
fixes.push(fixer.remove(typeAnnotation));
|
|
188
|
+
return fixes;
|
|
189
|
+
},
|
|
190
|
+
messageId: "inconsistent",
|
|
191
|
+
node
|
|
192
|
+
});
|
|
223
193
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
return {
|
|
229
|
-
plugins: {
|
|
230
|
-
[name]: plugin
|
|
231
|
-
},
|
|
232
|
-
rules
|
|
233
|
-
};
|
|
234
|
-
} else {
|
|
194
|
+
const consistentRefTypeAnnotation = createEslintRule({
|
|
195
|
+
create(context, optionsWithDefault) {
|
|
196
|
+
const options = optionsWithDefault[0] || {};
|
|
197
|
+
const allowInference = options.allowInference;
|
|
235
198
|
return {
|
|
236
|
-
|
|
237
|
-
|
|
199
|
+
VariableDeclaration: (node) => {
|
|
200
|
+
const declarations = node.declarations;
|
|
201
|
+
for (const declaration of declarations) {
|
|
202
|
+
if (declaration.type !== TSESTree.AST_NODE_TYPES.VariableDeclarator)
|
|
203
|
+
continue;
|
|
204
|
+
checkAssignmentDeclaration(context, node, declaration, { allowInference });
|
|
205
|
+
}
|
|
206
|
+
}
|
|
238
207
|
};
|
|
239
|
-
}
|
|
240
|
-
}
|
|
208
|
+
},
|
|
209
|
+
defaultOptions: [{ allowInference: false }],
|
|
210
|
+
meta: {
|
|
211
|
+
docs: {
|
|
212
|
+
description: "Ensures consistent type annotation position for ref, computed assignments",
|
|
213
|
+
recommendation: "recommended"
|
|
214
|
+
},
|
|
215
|
+
fixable: "code",
|
|
216
|
+
messages: {
|
|
217
|
+
inconsistent: `Generic type annotation for the {{ name }} call was not on the right side`,
|
|
218
|
+
missingType: `variable assignment for {{ name }} is missing the type annotation`
|
|
219
|
+
},
|
|
220
|
+
schema: [
|
|
221
|
+
{
|
|
222
|
+
additionalProperties: false,
|
|
223
|
+
properties: {
|
|
224
|
+
allowInference: {
|
|
225
|
+
type: "boolean"
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
type: "object"
|
|
229
|
+
}
|
|
230
|
+
],
|
|
231
|
+
type: "problem"
|
|
232
|
+
},
|
|
233
|
+
name: RULE_NAME$5
|
|
234
|
+
});
|
|
241
235
|
|
|
242
|
-
const RULE_NAME$
|
|
243
|
-
const debug$
|
|
236
|
+
const RULE_NAME$4 = "no-deprecated-classes";
|
|
237
|
+
const debug$2 = createDebug("@rotki/eslint-plugin:no-deprecated-classes");
|
|
244
238
|
const replacements$2 = [
|
|
245
239
|
["d-block", "block"],
|
|
246
240
|
["d-flex", "flex"],
|
|
@@ -300,7 +294,7 @@ function getRange(node) {
|
|
|
300
294
|
return node.range;
|
|
301
295
|
}
|
|
302
296
|
function reportReplacement(className, replacement, node, context, position = 1) {
|
|
303
|
-
debug$
|
|
297
|
+
debug$2(`found replacement ${replacement} for ${className}`);
|
|
304
298
|
const source = getSourceCode(context);
|
|
305
299
|
const initialRange = getRange(node);
|
|
306
300
|
const range = [
|
|
@@ -413,11 +407,11 @@ const noDeprecatedClasses = createEslintRule({
|
|
|
413
407
|
schema: [],
|
|
414
408
|
type: "problem"
|
|
415
409
|
},
|
|
416
|
-
name: RULE_NAME$
|
|
410
|
+
name: RULE_NAME$4
|
|
417
411
|
});
|
|
418
412
|
|
|
419
|
-
const debug$
|
|
420
|
-
const RULE_NAME$
|
|
413
|
+
const debug$1 = createDebug("@rotki/eslint-plugin:no-deprecated-components");
|
|
414
|
+
const RULE_NAME$3 = "no-deprecated-components";
|
|
421
415
|
const vuetify = {
|
|
422
416
|
VApp: true,
|
|
423
417
|
VAppBar: true,
|
|
@@ -470,7 +464,7 @@ const noDeprecatedComponents = createEslintRule({
|
|
|
470
464
|
return;
|
|
471
465
|
const replacement = replacements$1[tag];
|
|
472
466
|
if (replacement || legacy && skipInLegacy.includes(tag)) {
|
|
473
|
-
debug$
|
|
467
|
+
debug$1(`${tag} has been deprecated`);
|
|
474
468
|
context.report({
|
|
475
469
|
data: {
|
|
476
470
|
name: tag
|
|
@@ -479,7 +473,7 @@ const noDeprecatedComponents = createEslintRule({
|
|
|
479
473
|
node: element
|
|
480
474
|
});
|
|
481
475
|
} else {
|
|
482
|
-
debug$
|
|
476
|
+
debug$1(`${tag} has will be removed`);
|
|
483
477
|
context.report({
|
|
484
478
|
data: {
|
|
485
479
|
name: tag
|
|
@@ -522,11 +516,11 @@ const noDeprecatedComponents = createEslintRule({
|
|
|
522
516
|
],
|
|
523
517
|
type: "problem"
|
|
524
518
|
},
|
|
525
|
-
name: RULE_NAME$
|
|
519
|
+
name: RULE_NAME$3
|
|
526
520
|
});
|
|
527
521
|
|
|
528
|
-
const debug
|
|
529
|
-
const RULE_NAME$
|
|
522
|
+
const debug = createDebug("@rotki/eslint-plugin:no-deprecated-props");
|
|
523
|
+
const RULE_NAME$2 = "no-deprecated-props";
|
|
530
524
|
const replacements = {
|
|
531
525
|
RuiRadio: {
|
|
532
526
|
internalValue: "value"
|
|
@@ -552,16 +546,16 @@ const noDeprecatedProps = createEslintRule({
|
|
|
552
546
|
const tag = pascalCase(node.parent.parent.rawName);
|
|
553
547
|
if (!hasReplacement(tag))
|
|
554
548
|
return;
|
|
555
|
-
debug
|
|
549
|
+
debug(`${tag} has replacement properties`);
|
|
556
550
|
const propName = getPropName(node);
|
|
557
551
|
const propNameNode = node.directive ? node.key.argument : node.key;
|
|
558
552
|
if (!propName || !propNameNode) {
|
|
559
|
-
debug
|
|
553
|
+
debug("could not get prop name and/or node");
|
|
560
554
|
return;
|
|
561
555
|
}
|
|
562
556
|
Object.entries(replacements[tag]).forEach(([prop, replacement]) => {
|
|
563
557
|
if (kebabCase(prop) === propName) {
|
|
564
|
-
debug
|
|
558
|
+
debug(`preparing a replacement for ${tag}:${propName} -> ${replacement}`);
|
|
565
559
|
context.report({
|
|
566
560
|
data: {
|
|
567
561
|
prop,
|
|
@@ -591,24 +585,27 @@ const noDeprecatedProps = createEslintRule({
|
|
|
591
585
|
schema: [],
|
|
592
586
|
type: "problem"
|
|
593
587
|
},
|
|
594
|
-
name: RULE_NAME$
|
|
588
|
+
name: RULE_NAME$2
|
|
595
589
|
});
|
|
596
590
|
|
|
597
|
-
const RULE_NAME$
|
|
598
|
-
const
|
|
599
|
-
const newLibrary = "@rotki/ui-library";
|
|
600
|
-
const noLegacyLibraryImport = createEslintRule({
|
|
591
|
+
const RULE_NAME$1 = "no-dot-ts-imports";
|
|
592
|
+
const noDotTsImport = createEslintRule({
|
|
601
593
|
create(context) {
|
|
602
594
|
return {
|
|
603
595
|
ImportDeclaration(node) {
|
|
604
|
-
|
|
596
|
+
const importDeclaration = node.source.value;
|
|
597
|
+
if (!importDeclaration.endsWith(".ts"))
|
|
605
598
|
return;
|
|
606
|
-
const
|
|
599
|
+
const lastIndexOfExtension = importDeclaration.lastIndexOf(".ts");
|
|
600
|
+
const replacement = importDeclaration.substring(0, lastIndexOfExtension);
|
|
607
601
|
context.report({
|
|
602
|
+
data: {
|
|
603
|
+
import: importDeclaration
|
|
604
|
+
},
|
|
608
605
|
fix(fixer) {
|
|
609
606
|
return fixer.replaceText(node.source, `'${replacement}'`);
|
|
610
607
|
},
|
|
611
|
-
messageId: "
|
|
608
|
+
messageId: "invalidTSExtension",
|
|
612
609
|
node: node.source
|
|
613
610
|
});
|
|
614
611
|
}
|
|
@@ -617,136 +614,34 @@ const noLegacyLibraryImport = createEslintRule({
|
|
|
617
614
|
defaultOptions: [],
|
|
618
615
|
meta: {
|
|
619
616
|
docs: {
|
|
620
|
-
description:
|
|
617
|
+
description: "Checks and replaces .ts extension in import statements.",
|
|
621
618
|
recommendation: "recommended"
|
|
622
619
|
},
|
|
623
620
|
fixable: "code",
|
|
624
621
|
messages: {
|
|
625
|
-
|
|
622
|
+
invalidTSExtension: `'{{ import }}' has a .ts extension, please remove it'`
|
|
626
623
|
},
|
|
627
624
|
schema: [],
|
|
628
625
|
type: "problem"
|
|
629
626
|
},
|
|
630
|
-
name: RULE_NAME$2
|
|
631
|
-
});
|
|
632
|
-
|
|
633
|
-
const debug = createDebug("@rotki/eslint-plugin:consistent-ref-type-annotation");
|
|
634
|
-
const RULE_NAME$1 = "consistent-ref-type-annotation";
|
|
635
|
-
const FIXABLE_METHODS = ["ref", "computed"];
|
|
636
|
-
function checkAssignmentDeclaration(context, node, declaration, options) {
|
|
637
|
-
const source = getSourceCode(context);
|
|
638
|
-
const { allowInference } = options;
|
|
639
|
-
let declarationTypeArguments;
|
|
640
|
-
const init = declaration.init;
|
|
641
|
-
if (!(init && init.type === TSESTree.AST_NODE_TYPES.CallExpression))
|
|
642
|
-
return;
|
|
643
|
-
const callee = init.callee;
|
|
644
|
-
if (!(callee && callee.type === TSESTree.AST_NODE_TYPES.Identifier))
|
|
645
|
-
return;
|
|
646
|
-
if (!Array.prototype.includes.call(FIXABLE_METHODS, callee.name))
|
|
647
|
-
return;
|
|
648
|
-
const name = callee.name;
|
|
649
|
-
debug(`found ${name}, checking type arguments`);
|
|
650
|
-
const initializationTypeArguments = init.typeArguments;
|
|
651
|
-
const typeAnnotation = declaration.id.typeAnnotation;
|
|
652
|
-
if (typeAnnotation) {
|
|
653
|
-
const typeNode = typeAnnotation.typeAnnotation;
|
|
654
|
-
if (typeNode && typeNode.type === TSESTree.AST_NODE_TYPES.TSTypeReference)
|
|
655
|
-
declarationTypeArguments = typeNode.typeArguments;
|
|
656
|
-
}
|
|
657
|
-
if (initializationTypeArguments && !declarationTypeArguments)
|
|
658
|
-
return;
|
|
659
|
-
debug(`generating report for ${name}`);
|
|
660
|
-
if (!initializationTypeArguments && !declarationTypeArguments) {
|
|
661
|
-
if (allowInference) {
|
|
662
|
-
debug("type inference is allowed");
|
|
663
|
-
} else {
|
|
664
|
-
context.report({
|
|
665
|
-
data: {
|
|
666
|
-
name
|
|
667
|
-
},
|
|
668
|
-
messageId: "missingType",
|
|
669
|
-
node
|
|
670
|
-
});
|
|
671
|
-
}
|
|
672
|
-
return;
|
|
673
|
-
}
|
|
674
|
-
context.report({
|
|
675
|
-
data: {
|
|
676
|
-
name
|
|
677
|
-
},
|
|
678
|
-
fix(fixer) {
|
|
679
|
-
const fixes = [];
|
|
680
|
-
if (!initializationTypeArguments && callee)
|
|
681
|
-
fixes.push(fixer.insertTextAfter(callee, source.getText(declarationTypeArguments)));
|
|
682
|
-
if (typeAnnotation)
|
|
683
|
-
fixes.push(fixer.remove(typeAnnotation));
|
|
684
|
-
return fixes;
|
|
685
|
-
},
|
|
686
|
-
messageId: "inconsistent",
|
|
687
|
-
node
|
|
688
|
-
});
|
|
689
|
-
}
|
|
690
|
-
const consistentRefTypeAnnotation = createEslintRule({
|
|
691
|
-
create(context, optionsWithDefault) {
|
|
692
|
-
const options = optionsWithDefault[0] || {};
|
|
693
|
-
const allowInference = options.allowInference;
|
|
694
|
-
return {
|
|
695
|
-
VariableDeclaration: (node) => {
|
|
696
|
-
const declarations = node.declarations;
|
|
697
|
-
for (const declaration of declarations) {
|
|
698
|
-
if (declaration.type !== TSESTree.AST_NODE_TYPES.VariableDeclarator)
|
|
699
|
-
continue;
|
|
700
|
-
checkAssignmentDeclaration(context, node, declaration, { allowInference });
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
};
|
|
704
|
-
},
|
|
705
|
-
defaultOptions: [{ allowInference: false }],
|
|
706
|
-
meta: {
|
|
707
|
-
docs: {
|
|
708
|
-
description: "Ensures consistent type annotation position for ref, computed assignments",
|
|
709
|
-
recommendation: "recommended"
|
|
710
|
-
},
|
|
711
|
-
fixable: "code",
|
|
712
|
-
messages: {
|
|
713
|
-
inconsistent: `Generic type annotation for the {{ name }} call was not on the right side`,
|
|
714
|
-
missingType: `variable assignment for {{ name }} is missing the type annotation`
|
|
715
|
-
},
|
|
716
|
-
schema: [
|
|
717
|
-
{
|
|
718
|
-
additionalProperties: false,
|
|
719
|
-
properties: {
|
|
720
|
-
allowInference: {
|
|
721
|
-
type: "boolean"
|
|
722
|
-
}
|
|
723
|
-
},
|
|
724
|
-
type: "object"
|
|
725
|
-
}
|
|
726
|
-
],
|
|
727
|
-
type: "problem"
|
|
728
|
-
},
|
|
729
627
|
name: RULE_NAME$1
|
|
730
628
|
});
|
|
731
629
|
|
|
732
|
-
const RULE_NAME = "no-
|
|
733
|
-
const
|
|
630
|
+
const RULE_NAME = "no-legacy-library-import";
|
|
631
|
+
const legacyLibrary = "@rotki/ui-library-compat";
|
|
632
|
+
const newLibrary = "@rotki/ui-library";
|
|
633
|
+
const noLegacyLibraryImport = createEslintRule({
|
|
734
634
|
create(context) {
|
|
735
635
|
return {
|
|
736
636
|
ImportDeclaration(node) {
|
|
737
|
-
|
|
738
|
-
if (!importDeclaration.endsWith(".ts"))
|
|
637
|
+
if (!node.source.value.startsWith(legacyLibrary))
|
|
739
638
|
return;
|
|
740
|
-
const
|
|
741
|
-
const replacement = importDeclaration.substring(0, lastIndexOfExtension);
|
|
639
|
+
const replacement = node.source.value.replace(legacyLibrary, newLibrary);
|
|
742
640
|
context.report({
|
|
743
|
-
data: {
|
|
744
|
-
import: importDeclaration
|
|
745
|
-
},
|
|
746
641
|
fix(fixer) {
|
|
747
642
|
return fixer.replaceText(node.source, `'${replacement}'`);
|
|
748
643
|
},
|
|
749
|
-
messageId: "
|
|
644
|
+
messageId: "replacedWith",
|
|
750
645
|
node: node.source
|
|
751
646
|
});
|
|
752
647
|
}
|
|
@@ -755,12 +650,12 @@ const noDotTsImport = createEslintRule({
|
|
|
755
650
|
defaultOptions: [],
|
|
756
651
|
meta: {
|
|
757
652
|
docs: {
|
|
758
|
-
description:
|
|
653
|
+
description: `Reports and replaces imports of ${legacyLibrary} with ${newLibrary}`,
|
|
759
654
|
recommendation: "recommended"
|
|
760
655
|
},
|
|
761
656
|
fixable: "code",
|
|
762
657
|
messages: {
|
|
763
|
-
|
|
658
|
+
replacedWith: `${legacyLibrary} has been replaced by ${newLibrary}`
|
|
764
659
|
},
|
|
765
660
|
schema: [],
|
|
766
661
|
type: "problem"
|
|
@@ -782,13 +677,12 @@ const plugin = {
|
|
|
782
677
|
"no-legacy-library-import": noLegacyLibraryImport
|
|
783
678
|
}
|
|
784
679
|
};
|
|
785
|
-
const plugin$1 = plugin;
|
|
786
680
|
|
|
787
681
|
const configs = {
|
|
788
|
-
"recommended": createRecommended(plugin
|
|
789
|
-
"recommended-flat": createRecommended(plugin
|
|
682
|
+
"recommended": createRecommended(plugin, "@rotki", false),
|
|
683
|
+
"recommended-flat": createRecommended(plugin, "@rotki", true)
|
|
790
684
|
};
|
|
791
685
|
|
|
792
|
-
const index = Object.assign(plugin
|
|
686
|
+
const index = Object.assign(plugin, { configs });
|
|
793
687
|
|
|
794
688
|
export { index as default };
|