-
-
Notifications
You must be signed in to change notification settings - Fork 44
/
Copy pathno-deprecated-modulo-syntax.ts
130 lines (122 loc) · 3.94 KB
/
no-deprecated-modulo-syntax.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/**
* @author kazuya kawaguchi (a.k.a. kazupon)
*/
import type { AST as JSONAST } from 'jsonc-eslint-parser'
import type { AST as YAMLAST } from 'yaml-eslint-parser'
import type { RuleContext, RuleListener } from '../types'
import type { GetReportOffset } from '../utils/rule'
import type { CustomBlockVisitorFactory } from '../types/vue-parser-services'
import { extname } from 'node:path'
import debugBuilder from 'debug'
import { defineCustomBlocksVisitor, getLocaleMessages } from '../utils/index'
import {
getMessageSyntaxVersions,
NodeTypes
} from '../utils/message-compiler/utils'
import { parse } from '../utils/message-compiler/parser-v9'
import { traverseNode } from '../utils/message-compiler/traverser'
import {
createRule,
defineCreateVisitorForJson,
defineCreateVisitorForYaml
} from '../utils/rule'
import { getFilename, getSourceCode } from '../utils/compat'
const debug = debugBuilder('eslint-plugin-vue-i18n:no-deprecated-modulo-syntax')
function create(context: RuleContext): RuleListener {
const filename = getFilename(context)
const sourceCode = getSourceCode(context)
const messageSyntaxVersions = getMessageSyntaxVersions(context)
function verifyForV9(
message: string,
reportNode: JSONAST.JSONStringLiteral | YAMLAST.YAMLScalar,
getReportOffset: GetReportOffset
) {
const { ast, errors } = parse(message)
if (errors.length) {
return
}
traverseNode(ast, node => {
if (node.type !== NodeTypes.Named || !node.modulo) {
return
}
let range: [number, number] | null = null
const start = getReportOffset(node.loc!.start.offset)
const end = getReportOffset(node.loc!.end.offset)
if (start != null && end != null) {
// Subtract `%` length (1), because we want to fix modulo
range = [start - 1, end]
}
context.report({
loc: range
? {
start: sourceCode.getLocFromIndex(range[0]),
end: sourceCode.getLocFromIndex(range[1])
}
: reportNode.loc,
message:
'The modulo interpolation must be enforced to named interpolation.',
fix(fixer) {
return range ? fixer.removeRange([range[0], range[0] + 1]) : null
}
})
})
}
function verifyMessage(
message: string,
reportNode: JSONAST.JSONStringLiteral | YAMLAST.YAMLScalar,
getReportOffset: GetReportOffset
) {
if (messageSyntaxVersions.reportIfMissingSetting()) {
return
}
if (messageSyntaxVersions.v9) {
verifyForV9(message, reportNode, getReportOffset)
}
}
const createVisitorForJson = defineCreateVisitorForJson(verifyMessage)
const createVisitorForYaml = defineCreateVisitorForYaml(verifyMessage)
if (extname(filename) === '.vue') {
return defineCustomBlocksVisitor(
context,
createVisitorForJson,
createVisitorForYaml
)
} else if (
sourceCode.parserServices.isJSON ||
sourceCode.parserServices.isYAML
) {
const localeMessages = getLocaleMessages(context)
const targetLocaleMessage = localeMessages.findExistLocaleMessage(filename)
if (!targetLocaleMessage) {
debug(`ignore ${filename} in no-deprecated-modulo-syntax`)
return {}
}
if (sourceCode.parserServices.isJSON) {
return createVisitorForJson(
context as Parameters<CustomBlockVisitorFactory>[0]
)
} else if (sourceCode.parserServices.isYAML) {
return createVisitorForYaml(
context as Parameters<CustomBlockVisitorFactory>[0]
)
}
return {}
} else {
debug(`ignore ${filename} in no-deprecated-modulo-syntax`)
return {}
}
}
export = createRule({
meta: {
type: 'problem',
docs: {
description: 'enforce modulo interpolation to be named interpolation',
category: 'Recommended',
url: 'https://eslint-plugin-vue-i18n.intlify.dev/rules/no-deprecated-modulo-syntax.html',
recommended: true
},
fixable: 'code',
schema: []
},
create
})