@wsxjs/eslint-plugin-wsx 0.0.18 → 0.0.20
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/dist/index.js +103 -1
- package/dist/index.mjs +103 -1
- package/package.json +2 -2
- package/src/configs/recommended.ts +1 -0
- package/src/index.ts +2 -0
- package/src/rules/i18n-after-autoregister.ts +166 -0
package/dist/index.js
CHANGED
|
@@ -450,6 +450,106 @@ var noInnerHTML = {
|
|
|
450
450
|
}
|
|
451
451
|
};
|
|
452
452
|
|
|
453
|
+
// src/rules/i18n-after-autoregister.ts
|
|
454
|
+
var i18nAfterAutoRegister = {
|
|
455
|
+
meta: {
|
|
456
|
+
type: "problem",
|
|
457
|
+
docs: {
|
|
458
|
+
description: "require @i18n decorator to be after @autoRegister decorator",
|
|
459
|
+
category: "Possible Errors",
|
|
460
|
+
recommended: true
|
|
461
|
+
},
|
|
462
|
+
messages: {
|
|
463
|
+
wrongOrder: "@i18n decorator must be placed after @autoRegister decorator.\n\nCorrect order:\n @autoRegister({ tagName: 'my-component' })\n @i18n('common')\n export class MyComponent extends WebComponent {}\n\nThis is required because decorators execute from bottom to top."
|
|
464
|
+
},
|
|
465
|
+
schema: []
|
|
466
|
+
},
|
|
467
|
+
create(context) {
|
|
468
|
+
const autoRegisterImports = /* @__PURE__ */ new Set();
|
|
469
|
+
const i18nImports = /* @__PURE__ */ new Set();
|
|
470
|
+
return {
|
|
471
|
+
// Track imports to identify decorators
|
|
472
|
+
ImportDeclaration(node) {
|
|
473
|
+
if (node.source.type === "Literal" && typeof node.source.value === "string" && node.source.value === "@wsxjs/wsx-core") {
|
|
474
|
+
node.specifiers.forEach((specifier) => {
|
|
475
|
+
if (specifier.type === "ImportSpecifier") {
|
|
476
|
+
if (specifier.imported.type === "Identifier" && specifier.imported.name === "autoRegister") {
|
|
477
|
+
const localName = specifier.local.type === "Identifier" ? specifier.local.name : null;
|
|
478
|
+
if (localName) {
|
|
479
|
+
autoRegisterImports.add(localName);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
if (node.source.type === "Literal" && typeof node.source.value === "string" && node.source.value === "@wsxjs/wsx-i18next") {
|
|
486
|
+
node.specifiers.forEach((specifier) => {
|
|
487
|
+
if (specifier.type === "ImportSpecifier") {
|
|
488
|
+
if (specifier.imported.type === "Identifier" && specifier.imported.name === "i18n") {
|
|
489
|
+
const localName = specifier.local.type === "Identifier" ? specifier.local.name : null;
|
|
490
|
+
if (localName) {
|
|
491
|
+
i18nImports.add(localName);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
} else if (specifier.type === "ImportDefaultSpecifier") {
|
|
495
|
+
const localName = specifier.local.type === "Identifier" ? specifier.local.name : null;
|
|
496
|
+
if (localName) {
|
|
497
|
+
i18nImports.add(localName);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
},
|
|
503
|
+
// Check class decorators for correct order
|
|
504
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
505
|
+
"ClassDeclaration, ClassExpression"(node) {
|
|
506
|
+
if (!node.decorators || node.decorators.length < 2) {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
let autoRegisterIndex = -1;
|
|
510
|
+
let i18nIndex = -1;
|
|
511
|
+
node.decorators.forEach((decorator, index) => {
|
|
512
|
+
const isAutoRegister = (() => {
|
|
513
|
+
if (decorator.expression.type === "Identifier") {
|
|
514
|
+
return decorator.expression.name === "autoRegister" || autoRegisterImports.has(decorator.expression.name);
|
|
515
|
+
} else if (decorator.expression.type === "CallExpression") {
|
|
516
|
+
if (decorator.expression.callee.type === "Identifier") {
|
|
517
|
+
return decorator.expression.callee.name === "autoRegister" || autoRegisterImports.has(decorator.expression.callee.name);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return false;
|
|
521
|
+
})();
|
|
522
|
+
const isI18n = (() => {
|
|
523
|
+
if (decorator.expression.type === "Identifier") {
|
|
524
|
+
return decorator.expression.name === "i18n" || i18nImports.has(decorator.expression.name);
|
|
525
|
+
} else if (decorator.expression.type === "CallExpression") {
|
|
526
|
+
if (decorator.expression.callee.type === "Identifier") {
|
|
527
|
+
return decorator.expression.callee.name === "i18n" || i18nImports.has(decorator.expression.callee.name);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return false;
|
|
531
|
+
})();
|
|
532
|
+
if (isAutoRegister && autoRegisterIndex === -1) {
|
|
533
|
+
autoRegisterIndex = index;
|
|
534
|
+
}
|
|
535
|
+
if (isI18n && i18nIndex === -1) {
|
|
536
|
+
i18nIndex = index;
|
|
537
|
+
}
|
|
538
|
+
});
|
|
539
|
+
if (autoRegisterIndex !== -1 && i18nIndex !== -1) {
|
|
540
|
+
if (i18nIndex < autoRegisterIndex) {
|
|
541
|
+
const i18nDecorator = node.decorators[i18nIndex];
|
|
542
|
+
context.report({
|
|
543
|
+
node: i18nDecorator,
|
|
544
|
+
messageId: "wrongOrder"
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
|
|
453
553
|
// src/configs/recommended.ts
|
|
454
554
|
var recommendedConfig = {
|
|
455
555
|
parser: "@typescript-eslint/parser",
|
|
@@ -474,6 +574,7 @@ var recommendedConfig = {
|
|
|
474
574
|
"wsx/require-jsx-import-source": "error",
|
|
475
575
|
"wsx/no-null-render": "error",
|
|
476
576
|
"wsx/no-inner-html": "error",
|
|
577
|
+
"wsx/i18n-after-autoregister": "error",
|
|
477
578
|
// TypeScript 规则(推荐)
|
|
478
579
|
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
|
|
479
580
|
"@typescript-eslint/no-explicit-any": "warn",
|
|
@@ -642,7 +743,8 @@ var plugin = {
|
|
|
642
743
|
"state-requires-initial-value": stateRequiresInitialValue,
|
|
643
744
|
"require-jsx-import-source": requireJsxImportSource,
|
|
644
745
|
"no-null-render": noNullRender,
|
|
645
|
-
"no-inner-html": noInnerHTML
|
|
746
|
+
"no-inner-html": noInnerHTML,
|
|
747
|
+
"i18n-after-autoregister": i18nAfterAutoRegister
|
|
646
748
|
},
|
|
647
749
|
// 配置预设
|
|
648
750
|
configs: {
|
package/dist/index.mjs
CHANGED
|
@@ -421,6 +421,106 @@ var noInnerHTML = {
|
|
|
421
421
|
}
|
|
422
422
|
};
|
|
423
423
|
|
|
424
|
+
// src/rules/i18n-after-autoregister.ts
|
|
425
|
+
var i18nAfterAutoRegister = {
|
|
426
|
+
meta: {
|
|
427
|
+
type: "problem",
|
|
428
|
+
docs: {
|
|
429
|
+
description: "require @i18n decorator to be after @autoRegister decorator",
|
|
430
|
+
category: "Possible Errors",
|
|
431
|
+
recommended: true
|
|
432
|
+
},
|
|
433
|
+
messages: {
|
|
434
|
+
wrongOrder: "@i18n decorator must be placed after @autoRegister decorator.\n\nCorrect order:\n @autoRegister({ tagName: 'my-component' })\n @i18n('common')\n export class MyComponent extends WebComponent {}\n\nThis is required because decorators execute from bottom to top."
|
|
435
|
+
},
|
|
436
|
+
schema: []
|
|
437
|
+
},
|
|
438
|
+
create(context) {
|
|
439
|
+
const autoRegisterImports = /* @__PURE__ */ new Set();
|
|
440
|
+
const i18nImports = /* @__PURE__ */ new Set();
|
|
441
|
+
return {
|
|
442
|
+
// Track imports to identify decorators
|
|
443
|
+
ImportDeclaration(node) {
|
|
444
|
+
if (node.source.type === "Literal" && typeof node.source.value === "string" && node.source.value === "@wsxjs/wsx-core") {
|
|
445
|
+
node.specifiers.forEach((specifier) => {
|
|
446
|
+
if (specifier.type === "ImportSpecifier") {
|
|
447
|
+
if (specifier.imported.type === "Identifier" && specifier.imported.name === "autoRegister") {
|
|
448
|
+
const localName = specifier.local.type === "Identifier" ? specifier.local.name : null;
|
|
449
|
+
if (localName) {
|
|
450
|
+
autoRegisterImports.add(localName);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
if (node.source.type === "Literal" && typeof node.source.value === "string" && node.source.value === "@wsxjs/wsx-i18next") {
|
|
457
|
+
node.specifiers.forEach((specifier) => {
|
|
458
|
+
if (specifier.type === "ImportSpecifier") {
|
|
459
|
+
if (specifier.imported.type === "Identifier" && specifier.imported.name === "i18n") {
|
|
460
|
+
const localName = specifier.local.type === "Identifier" ? specifier.local.name : null;
|
|
461
|
+
if (localName) {
|
|
462
|
+
i18nImports.add(localName);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
} else if (specifier.type === "ImportDefaultSpecifier") {
|
|
466
|
+
const localName = specifier.local.type === "Identifier" ? specifier.local.name : null;
|
|
467
|
+
if (localName) {
|
|
468
|
+
i18nImports.add(localName);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
// Check class decorators for correct order
|
|
475
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
476
|
+
"ClassDeclaration, ClassExpression"(node) {
|
|
477
|
+
if (!node.decorators || node.decorators.length < 2) {
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
let autoRegisterIndex = -1;
|
|
481
|
+
let i18nIndex = -1;
|
|
482
|
+
node.decorators.forEach((decorator, index) => {
|
|
483
|
+
const isAutoRegister = (() => {
|
|
484
|
+
if (decorator.expression.type === "Identifier") {
|
|
485
|
+
return decorator.expression.name === "autoRegister" || autoRegisterImports.has(decorator.expression.name);
|
|
486
|
+
} else if (decorator.expression.type === "CallExpression") {
|
|
487
|
+
if (decorator.expression.callee.type === "Identifier") {
|
|
488
|
+
return decorator.expression.callee.name === "autoRegister" || autoRegisterImports.has(decorator.expression.callee.name);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return false;
|
|
492
|
+
})();
|
|
493
|
+
const isI18n = (() => {
|
|
494
|
+
if (decorator.expression.type === "Identifier") {
|
|
495
|
+
return decorator.expression.name === "i18n" || i18nImports.has(decorator.expression.name);
|
|
496
|
+
} else if (decorator.expression.type === "CallExpression") {
|
|
497
|
+
if (decorator.expression.callee.type === "Identifier") {
|
|
498
|
+
return decorator.expression.callee.name === "i18n" || i18nImports.has(decorator.expression.callee.name);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
return false;
|
|
502
|
+
})();
|
|
503
|
+
if (isAutoRegister && autoRegisterIndex === -1) {
|
|
504
|
+
autoRegisterIndex = index;
|
|
505
|
+
}
|
|
506
|
+
if (isI18n && i18nIndex === -1) {
|
|
507
|
+
i18nIndex = index;
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
if (autoRegisterIndex !== -1 && i18nIndex !== -1) {
|
|
511
|
+
if (i18nIndex < autoRegisterIndex) {
|
|
512
|
+
const i18nDecorator = node.decorators[i18nIndex];
|
|
513
|
+
context.report({
|
|
514
|
+
node: i18nDecorator,
|
|
515
|
+
messageId: "wrongOrder"
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
|
|
424
524
|
// src/configs/recommended.ts
|
|
425
525
|
var recommendedConfig = {
|
|
426
526
|
parser: "@typescript-eslint/parser",
|
|
@@ -445,6 +545,7 @@ var recommendedConfig = {
|
|
|
445
545
|
"wsx/require-jsx-import-source": "error",
|
|
446
546
|
"wsx/no-null-render": "error",
|
|
447
547
|
"wsx/no-inner-html": "error",
|
|
548
|
+
"wsx/i18n-after-autoregister": "error",
|
|
448
549
|
// TypeScript 规则(推荐)
|
|
449
550
|
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
|
|
450
551
|
"@typescript-eslint/no-explicit-any": "warn",
|
|
@@ -613,7 +714,8 @@ var plugin = {
|
|
|
613
714
|
"state-requires-initial-value": stateRequiresInitialValue,
|
|
614
715
|
"require-jsx-import-source": requireJsxImportSource,
|
|
615
716
|
"no-null-render": noNullRender,
|
|
616
|
-
"no-inner-html": noInnerHTML
|
|
717
|
+
"no-inner-html": noInnerHTML,
|
|
718
|
+
"i18n-after-autoregister": i18nAfterAutoRegister
|
|
617
719
|
},
|
|
618
720
|
// 配置预设
|
|
619
721
|
configs: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wsxjs/eslint-plugin-wsx",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.20",
|
|
4
4
|
"description": "ESLint plugin for WSXJS",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"web-components"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@wsxjs/wsx-core": "0.0.
|
|
28
|
+
"@wsxjs/wsx-core": "0.0.20"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"tsup": "^8.0.0",
|
|
@@ -28,6 +28,7 @@ export const recommendedConfig: WSXConfig = {
|
|
|
28
28
|
"wsx/require-jsx-import-source": "error",
|
|
29
29
|
"wsx/no-null-render": "error",
|
|
30
30
|
"wsx/no-inner-html": "error",
|
|
31
|
+
"wsx/i18n-after-autoregister": "error",
|
|
31
32
|
|
|
32
33
|
// TypeScript 规则(推荐)
|
|
33
34
|
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { stateRequiresInitialValue } from "./rules/state-requires-initial-value"
|
|
|
12
12
|
import { requireJsxImportSource } from "./rules/require-jsx-import-source";
|
|
13
13
|
import { noNullRender } from "./rules/no-null-render";
|
|
14
14
|
import { noInnerHTML } from "./rules/no-inner-html";
|
|
15
|
+
import { i18nAfterAutoRegister } from "./rules/i18n-after-autoregister";
|
|
15
16
|
import { recommendedConfig } from "./configs/recommended";
|
|
16
17
|
import { createFlatConfig } from "./configs/flat";
|
|
17
18
|
import { WSXPlugin } from "./types";
|
|
@@ -32,6 +33,7 @@ const plugin: WSXPlugin = {
|
|
|
32
33
|
"require-jsx-import-source": requireJsxImportSource,
|
|
33
34
|
"no-null-render": noNullRender,
|
|
34
35
|
"no-inner-html": noInnerHTML,
|
|
36
|
+
"i18n-after-autoregister": i18nAfterAutoRegister,
|
|
35
37
|
},
|
|
36
38
|
|
|
37
39
|
// 配置预设
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ESLint 规则:i18n-after-autoregister
|
|
3
|
+
*
|
|
4
|
+
* 确保 @i18n 装饰器必须在 @autoRegister 装饰器之后
|
|
5
|
+
* 这是因为装饰器的执行顺序是从下到上,@i18n 需要先应用,然后 @autoRegister 才能注册正确的类
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Rule } from "eslint";
|
|
9
|
+
import { WSXRuleModule } from "../types";
|
|
10
|
+
|
|
11
|
+
export const i18nAfterAutoRegister: WSXRuleModule = {
|
|
12
|
+
meta: {
|
|
13
|
+
type: "problem",
|
|
14
|
+
docs: {
|
|
15
|
+
description: "require @i18n decorator to be after @autoRegister decorator",
|
|
16
|
+
category: "Possible Errors",
|
|
17
|
+
recommended: true,
|
|
18
|
+
},
|
|
19
|
+
messages: {
|
|
20
|
+
wrongOrder:
|
|
21
|
+
"@i18n decorator must be placed after @autoRegister decorator.\n" +
|
|
22
|
+
"\n" +
|
|
23
|
+
"Correct order:\n" +
|
|
24
|
+
" @autoRegister({ tagName: 'my-component' })\n" +
|
|
25
|
+
" @i18n('common')\n" +
|
|
26
|
+
" export class MyComponent extends WebComponent {}\n" +
|
|
27
|
+
"\n" +
|
|
28
|
+
"This is required because decorators execute from bottom to top.",
|
|
29
|
+
},
|
|
30
|
+
schema: [],
|
|
31
|
+
},
|
|
32
|
+
create(context: Rule.RuleContext) {
|
|
33
|
+
// Track imported decorator identifiers
|
|
34
|
+
const autoRegisterImports = new Set<string>();
|
|
35
|
+
const i18nImports = new Set<string>();
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
// Track imports to identify decorators
|
|
39
|
+
ImportDeclaration(node) {
|
|
40
|
+
// Track @autoRegister from @wsxjs/wsx-core
|
|
41
|
+
if (
|
|
42
|
+
node.source.type === "Literal" &&
|
|
43
|
+
typeof node.source.value === "string" &&
|
|
44
|
+
node.source.value === "@wsxjs/wsx-core"
|
|
45
|
+
) {
|
|
46
|
+
node.specifiers.forEach((specifier) => {
|
|
47
|
+
if (specifier.type === "ImportSpecifier") {
|
|
48
|
+
if (
|
|
49
|
+
specifier.imported.type === "Identifier" &&
|
|
50
|
+
specifier.imported.name === "autoRegister"
|
|
51
|
+
) {
|
|
52
|
+
const localName =
|
|
53
|
+
specifier.local.type === "Identifier"
|
|
54
|
+
? specifier.local.name
|
|
55
|
+
: null;
|
|
56
|
+
if (localName) {
|
|
57
|
+
autoRegisterImports.add(localName);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Track @i18n from @wsxjs/wsx-i18next
|
|
65
|
+
if (
|
|
66
|
+
node.source.type === "Literal" &&
|
|
67
|
+
typeof node.source.value === "string" &&
|
|
68
|
+
node.source.value === "@wsxjs/wsx-i18next"
|
|
69
|
+
) {
|
|
70
|
+
node.specifiers.forEach((specifier) => {
|
|
71
|
+
if (specifier.type === "ImportSpecifier") {
|
|
72
|
+
if (
|
|
73
|
+
specifier.imported.type === "Identifier" &&
|
|
74
|
+
specifier.imported.name === "i18n"
|
|
75
|
+
) {
|
|
76
|
+
const localName =
|
|
77
|
+
specifier.local.type === "Identifier"
|
|
78
|
+
? specifier.local.name
|
|
79
|
+
: null;
|
|
80
|
+
if (localName) {
|
|
81
|
+
i18nImports.add(localName);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
} else if (specifier.type === "ImportDefaultSpecifier") {
|
|
85
|
+
// Handle default import: import i18n from '@wsxjs/wsx-i18next'
|
|
86
|
+
const localName =
|
|
87
|
+
specifier.local.type === "Identifier" ? specifier.local.name : null;
|
|
88
|
+
if (localName) {
|
|
89
|
+
i18nImports.add(localName);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
// Check class decorators for correct order
|
|
97
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
98
|
+
"ClassDeclaration, ClassExpression"(node: any) {
|
|
99
|
+
if (!node.decorators || node.decorators.length < 2) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Find positions of @autoRegister and @i18n decorators
|
|
104
|
+
let autoRegisterIndex = -1;
|
|
105
|
+
let i18nIndex = -1;
|
|
106
|
+
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
108
|
+
node.decorators.forEach((decorator: any, index: number) => {
|
|
109
|
+
const isAutoRegister = (() => {
|
|
110
|
+
if (decorator.expression.type === "Identifier") {
|
|
111
|
+
return (
|
|
112
|
+
decorator.expression.name === "autoRegister" ||
|
|
113
|
+
autoRegisterImports.has(decorator.expression.name)
|
|
114
|
+
);
|
|
115
|
+
} else if (decorator.expression.type === "CallExpression") {
|
|
116
|
+
if (decorator.expression.callee.type === "Identifier") {
|
|
117
|
+
return (
|
|
118
|
+
decorator.expression.callee.name === "autoRegister" ||
|
|
119
|
+
autoRegisterImports.has(decorator.expression.callee.name)
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return false;
|
|
124
|
+
})();
|
|
125
|
+
|
|
126
|
+
const isI18n = (() => {
|
|
127
|
+
if (decorator.expression.type === "Identifier") {
|
|
128
|
+
return (
|
|
129
|
+
decorator.expression.name === "i18n" ||
|
|
130
|
+
i18nImports.has(decorator.expression.name)
|
|
131
|
+
);
|
|
132
|
+
} else if (decorator.expression.type === "CallExpression") {
|
|
133
|
+
if (decorator.expression.callee.type === "Identifier") {
|
|
134
|
+
return (
|
|
135
|
+
decorator.expression.callee.name === "i18n" ||
|
|
136
|
+
i18nImports.has(decorator.expression.callee.name)
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return false;
|
|
141
|
+
})();
|
|
142
|
+
|
|
143
|
+
if (isAutoRegister && autoRegisterIndex === -1) {
|
|
144
|
+
autoRegisterIndex = index;
|
|
145
|
+
}
|
|
146
|
+
if (isI18n && i18nIndex === -1) {
|
|
147
|
+
i18nIndex = index;
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// If both decorators are present, check order
|
|
152
|
+
// Decorators execute from bottom to top, so @i18n should be after @autoRegister (higher index)
|
|
153
|
+
if (autoRegisterIndex !== -1 && i18nIndex !== -1) {
|
|
154
|
+
if (i18nIndex < autoRegisterIndex) {
|
|
155
|
+
// Find the @i18n decorator node to report the error
|
|
156
|
+
const i18nDecorator = node.decorators[i18nIndex];
|
|
157
|
+
context.report({
|
|
158
|
+
node: i18nDecorator,
|
|
159
|
+
messageId: "wrongOrder",
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
},
|
|
166
|
+
};
|