forked from mysticatea/eslint-plugin-node
-
-
Notifications
You must be signed in to change notification settings - Fork 33
/
check-unsupported-builtins.js
129 lines (113 loc) · 4.1 KB
/
check-unsupported-builtins.js
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
/**
* @author Toru Nagashima
* See LICENSE file in root directory for full license.
*/
"use strict"
const { major, rsort } = require("semver")
const { ReferenceTracker } = require("@eslint-community/eslint-utils")
const getConfiguredNodeVersion = require("./get-configured-node-version")
const getSemverRange = require("./get-semver-range")
const unprefixNodeColon = require("./unprefix-node-colon")
/**
* Parses the options.
* @param {import('eslint').Rule.RuleContext} context The rule context.
* @returns {Readonly<{
* version: import('semver').Range,
* ignores: Set<string>
* }>} Parsed value.
*/
function parseOptions(context) {
const raw = context.options[0] || {}
const version = getConfiguredNodeVersion(context)
const ignores = new Set(raw.ignores || [])
return Object.freeze({ version, ignores })
}
/**
* Check if it has been supported.
* @param {import('../unsupported-features/types.js').SupportInfo} info The support info.
* @param {import('semver').Range} configured The configured version range.
*/
function isSupported({ supported }, configured) {
if (supported == null || supported.length === 0) {
return false
}
const [latest] = rsort(supported)
const range = getSemverRange(
[
...supported.map(
version => `>= ${version} < ${major(version) + 1}`
),
`> ${major(latest)}`,
].join("||")
)
if (range == null) {
return false
}
return configured.intersects(range)
}
/**
* Get the formatted text of a given supported version.
* @param {import('../unsupported-features/types.js').SupportInfo} info The support info.
* @returns {string | undefined}
*/
function supportedVersionToString({ supported }) {
if (supported == null || supported.length === 0) {
return
}
const [latest, ...backported] = rsort(supported)
if (backported.length === 0) {
return latest
}
const backportString = backported.map(version => `^${version}`).join(", ")
return `${latest} (backported: ${backportString})`
}
/**
* Verify the code to report unsupported APIs.
* @param {import('eslint').Rule.RuleContext} context The rule context.
* @param {import('../unsupported-features/types.js').SupportVersionBuiltins} traceMap The map for APIs to report.
* @returns {void}
*/
module.exports.checkUnsupportedBuiltins = function checkUnsupportedBuiltins(
context,
traceMap
) {
const options = parseOptions(context)
const sourceCode = context.sourceCode ?? context.getSourceCode() // TODO: just use context.sourceCode when dropping eslint < v9
const scope = sourceCode.getScope?.(sourceCode.ast) ?? context.getScope() //TODO: remove context.getScope() when dropping support for ESLint < v9
const tracker = new ReferenceTracker(scope, { mode: "legacy" })
const references = [
...tracker.iterateCjsReferences(traceMap.modules ?? {}),
...tracker.iterateEsmReferences(traceMap.modules ?? {}),
...tracker.iterateGlobalReferences(traceMap.globals ?? {}),
]
for (const { node, path, info } of references) {
const name = unprefixNodeColon(path.join("."))
const supported = isSupported(info, options.version)
if (supported === true || options.ignores.has(name)) {
continue
}
const supportedVersion = supportedVersionToString(info)
context.report({
node,
messageId: supportedVersion
? "not-supported-till"
: "not-supported-yet",
data: {
name: path.join("."),
supported: /** @type string */ (supportedVersion),
version: options.version.raw,
},
})
}
}
exports.messages = {
"not-supported-till": [
"The '{{name}}' is still an experimental feature",
"and is not supported until Node.js {{supported}}.",
"The configured version range is '{{version}}'.",
].join(" "),
"not-supported-yet": [
"The '{{name}}' is still an experimental feature",
"The configured version range is '{{version}}'.",
].join(" "),
}