diff --git a/.changeset/no-intl-locale-prototype-firstdayofweek.md b/.changeset/no-intl-locale-prototype-firstdayofweek.md new file mode 100644 index 00000000..7d0e04bc --- /dev/null +++ b/.changeset/no-intl-locale-prototype-firstdayofweek.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-es-x": minor +--- + +Add `es-x/no-intl-locale-prototype-firstdayofweek` rule diff --git a/.changeset/no-intl-locale-prototype-getcalendars.md b/.changeset/no-intl-locale-prototype-getcalendars.md new file mode 100644 index 00000000..9cb2f6c0 --- /dev/null +++ b/.changeset/no-intl-locale-prototype-getcalendars.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-es-x": minor +--- + +Add `es-x/no-intl-locale-prototype-getcalendars` rule diff --git a/.changeset/no-intl-locale-prototype-getcollations.md b/.changeset/no-intl-locale-prototype-getcollations.md new file mode 100644 index 00000000..8a0dadd5 --- /dev/null +++ b/.changeset/no-intl-locale-prototype-getcollations.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-es-x": minor +--- + +Add `es-x/no-intl-locale-prototype-getcollations` rule diff --git a/.changeset/no-intl-locale-prototype-gethourcycles.md b/.changeset/no-intl-locale-prototype-gethourcycles.md new file mode 100644 index 00000000..a0a48767 --- /dev/null +++ b/.changeset/no-intl-locale-prototype-gethourcycles.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-es-x": minor +--- + +Add `es-x/no-intl-locale-prototype-gethourcycles` rule diff --git a/.changeset/no-intl-locale-prototype-getnumberingsystems.md b/.changeset/no-intl-locale-prototype-getnumberingsystems.md new file mode 100644 index 00000000..06c74bcf --- /dev/null +++ b/.changeset/no-intl-locale-prototype-getnumberingsystems.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-es-x": minor +--- + +Add `es-x/no-intl-locale-prototype-getnumberingsystems` rule diff --git a/.changeset/no-intl-locale-prototype-gettextinfo.md b/.changeset/no-intl-locale-prototype-gettextinfo.md new file mode 100644 index 00000000..dc7ba682 --- /dev/null +++ b/.changeset/no-intl-locale-prototype-gettextinfo.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-es-x": minor +--- + +Add `es-x/no-intl-locale-prototype-gettextinfo` rule diff --git a/.changeset/no-intl-locale-prototype-gettimezones.md b/.changeset/no-intl-locale-prototype-gettimezones.md new file mode 100644 index 00000000..2d99e78c --- /dev/null +++ b/.changeset/no-intl-locale-prototype-gettimezones.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-es-x": minor +--- + +Add `es-x/no-intl-locale-prototype-gettimezones` rule diff --git a/.changeset/no-intl-locale-prototype-getweekinfo.md b/.changeset/no-intl-locale-prototype-getweekinfo.md new file mode 100644 index 00000000..39e7caba --- /dev/null +++ b/.changeset/no-intl-locale-prototype-getweekinfo.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-es-x": minor +--- + +Add `es-x/no-intl-locale-prototype-getweekinfo` rule diff --git a/docs/configs/index.md b/docs/configs/index.md index 6518794b..5fd8d126 100644 --- a/docs/configs/index.md +++ b/docs/configs/index.md @@ -26,6 +26,30 @@ export default [ +## no-new-in-esnext-intl-api + +disallow the new stuff to be planned for the next yearly ECMAScript Intl API (ECMA-402) snapshot.\ +⚠️ This config will be changed in the minor versions of this plugin. + +```js +import pluginESx from "eslint-plugin-es-x" +export default [ + pluginESx.configs['flat/no-new-in-esnext-intl-api'] +] +``` + +
Legacy Config + +.eslintrc.*: + +```json +{ + "extends": ["plugin:es-x/no-new-in-esnext-intl-api"], +} +``` + +
+ ## no-new-in-es2025 disallow new stuff in ES2025. @@ -1041,6 +1065,32 @@ export default [ +## no-intl-locale-info + +disallow proposal ES2026 Intl API [Intl Locale Info API](https://github.com/tc39/proposal-intl-locale-info)\ +⚠️ This config will be changed in the minor versions of this plugin. + +This configs includes rules for [es-x/no-intl-locale-prototype-firstdayofweek](../rules/no-intl-locale-prototype-firstdayofweek.md), [es-x/no-intl-locale-prototype-getcalendars](../rules/no-intl-locale-prototype-getcalendars.md), [es-x/no-intl-locale-prototype-getcollations](../rules/no-intl-locale-prototype-getcollations.md), [es-x/no-intl-locale-prototype-gethourcycles](../rules/no-intl-locale-prototype-gethourcycles.md), [es-x/no-intl-locale-prototype-getnumberingsystems](../rules/no-intl-locale-prototype-getnumberingsystems.md), [es-x/no-intl-locale-prototype-gettextinfo](../rules/no-intl-locale-prototype-gettextinfo.md), [es-x/no-intl-locale-prototype-gettimezones](../rules/no-intl-locale-prototype-gettimezones.md), and [es-x/no-intl-locale-prototype-getweekinfo](../rules/no-intl-locale-prototype-getweekinfo.md). + +```js +import pluginESx from "eslint-plugin-es-x" +export default [ + pluginESx.configs['flat/no-intl-locale-info'] +] +``` + +
Legacy Config + +.eslintrc.*: + +```json +{ + "extends": ["plugin:es-x/no-intl-locale-info"], +} +``` + +
+ ## no-float16array disallow proposal ES2025 [Float16Array](https://github.com/tc39/proposal-float16array) diff --git a/docs/rules/index.md b/docs/rules/index.md index cf6db172..01300c6a 100644 --- a/docs/rules/index.md +++ b/docs/rules/index.md @@ -19,6 +19,21 @@ There is a config that enables the rules in this category: [`no-new-in-esnext`] | [es-x/no-symbol-dispose](./no-symbol-dispose.md) | disallow the `Symbol.dispose` property. | | | [es-x/no-using-declarations](./no-using-declarations.md) | disallow `using` and `await using` declarations. | | +## ES2026 Intl API + +There is a config that enables the rules in this category: [`no-new-in-esnext-intl-api`] + +| Rule ID | Description | | +|:--------|:------------|:--:| +| [es-x/no-intl-locale-prototype-firstdayofweek](./no-intl-locale-prototype-firstdayofweek.md) | disallow the `Intl.Locale.prototype.firstDayOfWeek` property. | | +| [es-x/no-intl-locale-prototype-getcalendars](./no-intl-locale-prototype-getcalendars.md) | disallow the `Intl.Locale.prototype.getCalendars` method. | | +| [es-x/no-intl-locale-prototype-getcollations](./no-intl-locale-prototype-getcollations.md) | disallow the `Intl.Locale.prototype.getCollations` method. | | +| [es-x/no-intl-locale-prototype-gethourcycles](./no-intl-locale-prototype-gethourcycles.md) | disallow the `Intl.Locale.prototype.getHourCycles` method. | | +| [es-x/no-intl-locale-prototype-getnumberingsystems](./no-intl-locale-prototype-getnumberingsystems.md) | disallow the `Intl.Locale.prototype.getNumberingSystems` method. | | +| [es-x/no-intl-locale-prototype-gettextinfo](./no-intl-locale-prototype-gettextinfo.md) | disallow the `Intl.Locale.prototype.getTextInfo` method. | | +| [es-x/no-intl-locale-prototype-gettimezones](./no-intl-locale-prototype-gettimezones.md) | disallow the `Intl.Locale.prototype.getTimeZones` method. | | +| [es-x/no-intl-locale-prototype-getweekinfo](./no-intl-locale-prototype-getweekinfo.md) | disallow the `Intl.Locale.prototype.getWeekInfo` method. | | + ## ES2025 There are multiple configs that enable all rules in this category: [`no-new-in-es2025`], [`restrict-to-es3`], [`restrict-to-es5`], [`restrict-to-es2015`], [`restrict-to-es2016`], [`restrict-to-es2017`], [`restrict-to-es2018`], [`restrict-to-es2019`], [`restrict-to-es2020`], [`restrict-to-es2021`], [`restrict-to-es2022`], [`restrict-to-es2023`], and [`restrict-to-es2024`] @@ -498,6 +513,7 @@ Rules in this category are not included in any preset. | [es-x/no-string-prototype-iswellformed-towellformed](./no-string-prototype-iswellformed-towellformed.md) | [es-x/no-string-prototype-iswellformed](./no-string-prototype-iswellformed.md), [es-x/no-string-prototype-towellformed](./no-string-prototype-towellformed.md) | [`no-new-in-esnext`]: ../configs/index.md#no-new-in-esnext +[`no-new-in-esnext-intl-api`]: ../configs/index.md#no-new-in-esnext-intl-api [`no-new-in-es2025`]: ../configs/index.md#no-new-in-es2025 [`restrict-to-es2024`]: ../configs/index.md#restrict-to-es2024 [`no-new-in-es2025-intl-api`]: ../configs/index.md#no-new-in-es2025-intl-api diff --git a/docs/rules/no-intl-locale-prototype-firstdayofweek.md b/docs/rules/no-intl-locale-prototype-firstdayofweek.md new file mode 100644 index 00000000..b7243c36 --- /dev/null +++ b/docs/rules/no-intl-locale-prototype-firstdayofweek.md @@ -0,0 +1,62 @@ +--- +title: "es-x/no-intl-locale-prototype-firstdayofweek" +description: "disallow the `Intl.Locale.prototype.firstDayOfWeek` property" +--- + +# es-x/no-intl-locale-prototype-firstdayofweek +> disallow the `Intl.Locale.prototype.firstDayOfWeek` property + +- ❗ ***This rule has not been released yet.*** +- ✅ The following configurations enable this rule: [no-intl-locale-info] and [no-new-in-esnext-intl-api] + +This rule reports ES2026 Intl API [`Intl.Locale.prototype.firstDayOfWeek` property](https://github.com/tc39/proposal-intl-locale-info) as errors. + +## 💡 Examples + +⛔ Examples of **incorrect** code for this rule: + + + +```js +/*eslint es-x/no-intl-locale-prototype-firstdayofweek: error */ +const foo = new Intl.Locale(); +foo.firstDayOfWeek; +``` + + + +## 🔧 Options + +This rule has an option. + +```jsonc +{ + "rules": { + "es-x/no-intl-locale-prototype-firstdayofweek": [ + "error", + { + "aggressive": false, + "allowTestedProperty": false + } + ] + } +} +``` + +### aggressive: boolean + +Configure the aggressive mode for only this rule. +This is prior to the `settings['es-x'].aggressive` setting. + +### allowTestedProperty: boolean + +Configure the allowTestedProperty mode for only this rule. +This is prior to the `settings['es-x'].allowTestedProperty` setting. + +## 📚 References + +- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-intl-locale-prototype-firstdayofweek.js) +- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-intl-locale-prototype-firstdayofweek.js) + +[no-intl-locale-info]: ../configs/index.md#no-intl-locale-info +[no-new-in-esnext-intl-api]: ../configs/index.md#no-new-in-esnext-intl-api diff --git a/docs/rules/no-intl-locale-prototype-getcalendars.md b/docs/rules/no-intl-locale-prototype-getcalendars.md new file mode 100644 index 00000000..50ff8ec1 --- /dev/null +++ b/docs/rules/no-intl-locale-prototype-getcalendars.md @@ -0,0 +1,62 @@ +--- +title: "es-x/no-intl-locale-prototype-getcalendars" +description: "disallow the `Intl.Locale.prototype.getCalendars` method" +--- + +# es-x/no-intl-locale-prototype-getcalendars +> disallow the `Intl.Locale.prototype.getCalendars` method + +- ❗ ***This rule has not been released yet.*** +- ✅ The following configurations enable this rule: [no-intl-locale-info] and [no-new-in-esnext-intl-api] + +This rule reports ES2026 Intl API [`Intl.Locale.prototype.getCalendars` method](https://github.com/tc39/proposal-intl-locale-info) as errors. + +## 💡 Examples + +⛔ Examples of **incorrect** code for this rule: + + + +```js +/*eslint es-x/no-intl-locale-prototype-getcalendars: error */ +const foo = new Intl.Locale(); +foo.getCalendars(); +``` + + + +## 🔧 Options + +This rule has an option. + +```jsonc +{ + "rules": { + "es-x/no-intl-locale-prototype-getcalendars": [ + "error", + { + "aggressive": false, + "allowTestedProperty": false + } + ] + } +} +``` + +### aggressive: boolean + +Configure the aggressive mode for only this rule. +This is prior to the `settings['es-x'].aggressive` setting. + +### allowTestedProperty: boolean + +Configure the allowTestedProperty mode for only this rule. +This is prior to the `settings['es-x'].allowTestedProperty` setting. + +## 📚 References + +- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-intl-locale-prototype-getcalendars.js) +- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-intl-locale-prototype-getcalendars.js) + +[no-intl-locale-info]: ../configs/index.md#no-intl-locale-info +[no-new-in-esnext-intl-api]: ../configs/index.md#no-new-in-esnext-intl-api diff --git a/docs/rules/no-intl-locale-prototype-getcollations.md b/docs/rules/no-intl-locale-prototype-getcollations.md new file mode 100644 index 00000000..f1813d37 --- /dev/null +++ b/docs/rules/no-intl-locale-prototype-getcollations.md @@ -0,0 +1,62 @@ +--- +title: "es-x/no-intl-locale-prototype-getcollations" +description: "disallow the `Intl.Locale.prototype.getCollations` method" +--- + +# es-x/no-intl-locale-prototype-getcollations +> disallow the `Intl.Locale.prototype.getCollations` method + +- ❗ ***This rule has not been released yet.*** +- ✅ The following configurations enable this rule: [no-intl-locale-info] and [no-new-in-esnext-intl-api] + +This rule reports ES2026 Intl API [`Intl.Locale.prototype.getCollations` method](https://github.com/tc39/proposal-intl-locale-info) as errors. + +## 💡 Examples + +⛔ Examples of **incorrect** code for this rule: + + + +```js +/*eslint es-x/no-intl-locale-prototype-getcollations: error */ +const foo = new Intl.Locale(); +foo.getCollations(); +``` + + + +## 🔧 Options + +This rule has an option. + +```jsonc +{ + "rules": { + "es-x/no-intl-locale-prototype-getcollations": [ + "error", + { + "aggressive": false, + "allowTestedProperty": false + } + ] + } +} +``` + +### aggressive: boolean + +Configure the aggressive mode for only this rule. +This is prior to the `settings['es-x'].aggressive` setting. + +### allowTestedProperty: boolean + +Configure the allowTestedProperty mode for only this rule. +This is prior to the `settings['es-x'].allowTestedProperty` setting. + +## 📚 References + +- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-intl-locale-prototype-getcollations.js) +- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-intl-locale-prototype-getcollations.js) + +[no-intl-locale-info]: ../configs/index.md#no-intl-locale-info +[no-new-in-esnext-intl-api]: ../configs/index.md#no-new-in-esnext-intl-api diff --git a/docs/rules/no-intl-locale-prototype-gethourcycles.md b/docs/rules/no-intl-locale-prototype-gethourcycles.md new file mode 100644 index 00000000..9eeb44bc --- /dev/null +++ b/docs/rules/no-intl-locale-prototype-gethourcycles.md @@ -0,0 +1,62 @@ +--- +title: "es-x/no-intl-locale-prototype-gethourcycles" +description: "disallow the `Intl.Locale.prototype.getHourCycles` method" +--- + +# es-x/no-intl-locale-prototype-gethourcycles +> disallow the `Intl.Locale.prototype.getHourCycles` method + +- ❗ ***This rule has not been released yet.*** +- ✅ The following configurations enable this rule: [no-intl-locale-info] and [no-new-in-esnext-intl-api] + +This rule reports ES2026 Intl API [`Intl.Locale.prototype.getHourCycles` method](https://github.com/tc39/proposal-intl-locale-info) as errors. + +## 💡 Examples + +⛔ Examples of **incorrect** code for this rule: + + + +```js +/*eslint es-x/no-intl-locale-prototype-gethourcycles: error */ +const foo = new Intl.Locale(); +foo.getHourCycles(); +``` + + + +## 🔧 Options + +This rule has an option. + +```jsonc +{ + "rules": { + "es-x/no-intl-locale-prototype-gethourcycles": [ + "error", + { + "aggressive": false, + "allowTestedProperty": false + } + ] + } +} +``` + +### aggressive: boolean + +Configure the aggressive mode for only this rule. +This is prior to the `settings['es-x'].aggressive` setting. + +### allowTestedProperty: boolean + +Configure the allowTestedProperty mode for only this rule. +This is prior to the `settings['es-x'].allowTestedProperty` setting. + +## 📚 References + +- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-intl-locale-prototype-gethourcycles.js) +- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-intl-locale-prototype-gethourcycles.js) + +[no-intl-locale-info]: ../configs/index.md#no-intl-locale-info +[no-new-in-esnext-intl-api]: ../configs/index.md#no-new-in-esnext-intl-api diff --git a/docs/rules/no-intl-locale-prototype-getnumberingsystems.md b/docs/rules/no-intl-locale-prototype-getnumberingsystems.md new file mode 100644 index 00000000..e30daad0 --- /dev/null +++ b/docs/rules/no-intl-locale-prototype-getnumberingsystems.md @@ -0,0 +1,62 @@ +--- +title: "es-x/no-intl-locale-prototype-getnumberingsystems" +description: "disallow the `Intl.Locale.prototype.getNumberingSystems` method" +--- + +# es-x/no-intl-locale-prototype-getnumberingsystems +> disallow the `Intl.Locale.prototype.getNumberingSystems` method + +- ❗ ***This rule has not been released yet.*** +- ✅ The following configurations enable this rule: [no-intl-locale-info] and [no-new-in-esnext-intl-api] + +This rule reports ES2026 Intl API [`Intl.Locale.prototype.getNumberingSystems` method](https://github.com/tc39/proposal-intl-locale-info) as errors. + +## 💡 Examples + +⛔ Examples of **incorrect** code for this rule: + + + +```js +/*eslint es-x/no-intl-locale-prototype-getnumberingsystems: error */ +const foo = new Intl.Locale(); +foo.getNumberingSystems(); +``` + + + +## 🔧 Options + +This rule has an option. + +```jsonc +{ + "rules": { + "es-x/no-intl-locale-prototype-getnumberingsystems": [ + "error", + { + "aggressive": false, + "allowTestedProperty": false + } + ] + } +} +``` + +### aggressive: boolean + +Configure the aggressive mode for only this rule. +This is prior to the `settings['es-x'].aggressive` setting. + +### allowTestedProperty: boolean + +Configure the allowTestedProperty mode for only this rule. +This is prior to the `settings['es-x'].allowTestedProperty` setting. + +## 📚 References + +- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-intl-locale-prototype-getnumberingsystems.js) +- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-intl-locale-prototype-getnumberingsystems.js) + +[no-intl-locale-info]: ../configs/index.md#no-intl-locale-info +[no-new-in-esnext-intl-api]: ../configs/index.md#no-new-in-esnext-intl-api diff --git a/docs/rules/no-intl-locale-prototype-gettextinfo.md b/docs/rules/no-intl-locale-prototype-gettextinfo.md new file mode 100644 index 00000000..9f7b30ee --- /dev/null +++ b/docs/rules/no-intl-locale-prototype-gettextinfo.md @@ -0,0 +1,62 @@ +--- +title: "es-x/no-intl-locale-prototype-gettextinfo" +description: "disallow the `Intl.Locale.prototype.getTextInfo` method" +--- + +# es-x/no-intl-locale-prototype-gettextinfo +> disallow the `Intl.Locale.prototype.getTextInfo` method + +- ❗ ***This rule has not been released yet.*** +- ✅ The following configurations enable this rule: [no-intl-locale-info] and [no-new-in-esnext-intl-api] + +This rule reports ES2026 Intl API [`Intl.Locale.prototype.getTextInfo` method](https://github.com/tc39/proposal-intl-locale-info) as errors. + +## 💡 Examples + +⛔ Examples of **incorrect** code for this rule: + + + +```js +/*eslint es-x/no-intl-locale-prototype-gettextinfo: error */ +const foo = new Intl.Locale(); +foo.getTextInfo(); +``` + + + +## 🔧 Options + +This rule has an option. + +```jsonc +{ + "rules": { + "es-x/no-intl-locale-prototype-gettextinfo": [ + "error", + { + "aggressive": false, + "allowTestedProperty": false + } + ] + } +} +``` + +### aggressive: boolean + +Configure the aggressive mode for only this rule. +This is prior to the `settings['es-x'].aggressive` setting. + +### allowTestedProperty: boolean + +Configure the allowTestedProperty mode for only this rule. +This is prior to the `settings['es-x'].allowTestedProperty` setting. + +## 📚 References + +- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-intl-locale-prototype-gettextinfo.js) +- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-intl-locale-prototype-gettextinfo.js) + +[no-intl-locale-info]: ../configs/index.md#no-intl-locale-info +[no-new-in-esnext-intl-api]: ../configs/index.md#no-new-in-esnext-intl-api diff --git a/docs/rules/no-intl-locale-prototype-gettimezones.md b/docs/rules/no-intl-locale-prototype-gettimezones.md new file mode 100644 index 00000000..755dc30d --- /dev/null +++ b/docs/rules/no-intl-locale-prototype-gettimezones.md @@ -0,0 +1,62 @@ +--- +title: "es-x/no-intl-locale-prototype-gettimezones" +description: "disallow the `Intl.Locale.prototype.getTimeZones` method" +--- + +# es-x/no-intl-locale-prototype-gettimezones +> disallow the `Intl.Locale.prototype.getTimeZones` method + +- ❗ ***This rule has not been released yet.*** +- ✅ The following configurations enable this rule: [no-intl-locale-info] and [no-new-in-esnext-intl-api] + +This rule reports ES2026 Intl API [`Intl.Locale.prototype.getTimeZones` method](https://github.com/tc39/proposal-intl-locale-info) as errors. + +## 💡 Examples + +⛔ Examples of **incorrect** code for this rule: + + + +```js +/*eslint es-x/no-intl-locale-prototype-gettimezones: error */ +const foo = new Intl.Locale(); +foo.getTimeZones(); +``` + + + +## 🔧 Options + +This rule has an option. + +```jsonc +{ + "rules": { + "es-x/no-intl-locale-prototype-gettimezones": [ + "error", + { + "aggressive": false, + "allowTestedProperty": false + } + ] + } +} +``` + +### aggressive: boolean + +Configure the aggressive mode for only this rule. +This is prior to the `settings['es-x'].aggressive` setting. + +### allowTestedProperty: boolean + +Configure the allowTestedProperty mode for only this rule. +This is prior to the `settings['es-x'].allowTestedProperty` setting. + +## 📚 References + +- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-intl-locale-prototype-gettimezones.js) +- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-intl-locale-prototype-gettimezones.js) + +[no-intl-locale-info]: ../configs/index.md#no-intl-locale-info +[no-new-in-esnext-intl-api]: ../configs/index.md#no-new-in-esnext-intl-api diff --git a/docs/rules/no-intl-locale-prototype-getweekinfo.md b/docs/rules/no-intl-locale-prototype-getweekinfo.md new file mode 100644 index 00000000..7fa11e3f --- /dev/null +++ b/docs/rules/no-intl-locale-prototype-getweekinfo.md @@ -0,0 +1,62 @@ +--- +title: "es-x/no-intl-locale-prototype-getweekinfo" +description: "disallow the `Intl.Locale.prototype.getWeekInfo` method" +--- + +# es-x/no-intl-locale-prototype-getweekinfo +> disallow the `Intl.Locale.prototype.getWeekInfo` method + +- ❗ ***This rule has not been released yet.*** +- ✅ The following configurations enable this rule: [no-intl-locale-info] and [no-new-in-esnext-intl-api] + +This rule reports ES2026 Intl API [`Intl.Locale.prototype.getWeekInfo` method](https://github.com/tc39/proposal-intl-locale-info) as errors. + +## 💡 Examples + +⛔ Examples of **incorrect** code for this rule: + + + +```js +/*eslint es-x/no-intl-locale-prototype-getweekinfo: error */ +const foo = new Intl.Locale(); +foo.getWeekInfo(); +``` + + + +## 🔧 Options + +This rule has an option. + +```jsonc +{ + "rules": { + "es-x/no-intl-locale-prototype-getweekinfo": [ + "error", + { + "aggressive": false, + "allowTestedProperty": false + } + ] + } +} +``` + +### aggressive: boolean + +Configure the aggressive mode for only this rule. +This is prior to the `settings['es-x'].aggressive` setting. + +### allowTestedProperty: boolean + +Configure the allowTestedProperty mode for only this rule. +This is prior to the `settings['es-x'].allowTestedProperty` setting. + +## 📚 References + +- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-intl-locale-prototype-getweekinfo.js) +- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-intl-locale-prototype-getweekinfo.js) + +[no-intl-locale-info]: ../configs/index.md#no-intl-locale-info +[no-new-in-esnext-intl-api]: ../configs/index.md#no-new-in-esnext-intl-api diff --git a/lib/configs/flat/no-intl-locale-info.js b/lib/configs/flat/no-intl-locale-info.js new file mode 100644 index 00000000..1ef55576 --- /dev/null +++ b/lib/configs/flat/no-intl-locale-info.js @@ -0,0 +1,23 @@ +/** + * DON'T EDIT THIS FILE. + * This file was generated by "scripts/update-lib-flat-configs.js" script. + */ +"use strict" + +module.exports = { + plugins: { + get "es-x"() { + return require("../../index.js") + }, + }, + rules: { + "es-x/no-intl-locale-prototype-firstdayofweek": "error", + "es-x/no-intl-locale-prototype-getcalendars": "error", + "es-x/no-intl-locale-prototype-getcollations": "error", + "es-x/no-intl-locale-prototype-gethourcycles": "error", + "es-x/no-intl-locale-prototype-getnumberingsystems": "error", + "es-x/no-intl-locale-prototype-gettextinfo": "error", + "es-x/no-intl-locale-prototype-gettimezones": "error", + "es-x/no-intl-locale-prototype-getweekinfo": "error", + }, +} diff --git a/lib/configs/flat/no-new-in-esnext-intl-api.js b/lib/configs/flat/no-new-in-esnext-intl-api.js index 270272d3..1ef55576 100644 --- a/lib/configs/flat/no-new-in-esnext-intl-api.js +++ b/lib/configs/flat/no-new-in-esnext-intl-api.js @@ -10,5 +10,14 @@ module.exports = { return require("../../index.js") }, }, - rules: {}, + rules: { + "es-x/no-intl-locale-prototype-firstdayofweek": "error", + "es-x/no-intl-locale-prototype-getcalendars": "error", + "es-x/no-intl-locale-prototype-getcollations": "error", + "es-x/no-intl-locale-prototype-gethourcycles": "error", + "es-x/no-intl-locale-prototype-getnumberingsystems": "error", + "es-x/no-intl-locale-prototype-gettextinfo": "error", + "es-x/no-intl-locale-prototype-gettimezones": "error", + "es-x/no-intl-locale-prototype-getweekinfo": "error", + }, } diff --git a/lib/configs/no-intl-locale-info.js b/lib/configs/no-intl-locale-info.js new file mode 100644 index 00000000..97b5893b --- /dev/null +++ b/lib/configs/no-intl-locale-info.js @@ -0,0 +1,19 @@ +/** + * DON'T EDIT THIS FILE. + * This file was generated by "scripts/update-lib-configs.js" script. + */ +"use strict" + +module.exports = { + plugins: ["es-x"], + rules: { + "es-x/no-intl-locale-prototype-firstdayofweek": "error", + "es-x/no-intl-locale-prototype-getcalendars": "error", + "es-x/no-intl-locale-prototype-getcollations": "error", + "es-x/no-intl-locale-prototype-gethourcycles": "error", + "es-x/no-intl-locale-prototype-getnumberingsystems": "error", + "es-x/no-intl-locale-prototype-gettextinfo": "error", + "es-x/no-intl-locale-prototype-gettimezones": "error", + "es-x/no-intl-locale-prototype-getweekinfo": "error", + }, +} diff --git a/lib/configs/no-new-in-esnext-intl-api.js b/lib/configs/no-new-in-esnext-intl-api.js index f42c5997..97b5893b 100644 --- a/lib/configs/no-new-in-esnext-intl-api.js +++ b/lib/configs/no-new-in-esnext-intl-api.js @@ -4,4 +4,16 @@ */ "use strict" -module.exports = { plugins: ["es-x"], rules: {} } +module.exports = { + plugins: ["es-x"], + rules: { + "es-x/no-intl-locale-prototype-firstdayofweek": "error", + "es-x/no-intl-locale-prototype-getcalendars": "error", + "es-x/no-intl-locale-prototype-getcollations": "error", + "es-x/no-intl-locale-prototype-gethourcycles": "error", + "es-x/no-intl-locale-prototype-getnumberingsystems": "error", + "es-x/no-intl-locale-prototype-gettextinfo": "error", + "es-x/no-intl-locale-prototype-gettimezones": "error", + "es-x/no-intl-locale-prototype-getweekinfo": "error", + }, +} diff --git a/lib/index.js b/lib/index.js index b523641b..5307256c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -16,6 +16,7 @@ module.exports = { "flat/no-explicit-resource-management": require("./configs/flat/no-explicit-resource-management"), "flat/no-float16array": require("./configs/flat/no-float16array"), "flat/no-import-attributes": require("./configs/flat/no-import-attributes"), + "flat/no-intl-locale-info": require("./configs/flat/no-intl-locale-info"), "flat/no-intl-numberformat-v3": require("./configs/flat/no-intl-numberformat-v3"), "flat/no-is-usv-string": require("./configs/flat/no-is-usv-string"), "flat/no-iterator-helpers": require("./configs/flat/no-iterator-helpers"), @@ -76,6 +77,7 @@ module.exports = { "no-explicit-resource-management": require("./configs/no-explicit-resource-management"), "no-float16array": require("./configs/no-float16array"), "no-import-attributes": require("./configs/no-import-attributes"), + "no-intl-locale-info": require("./configs/no-intl-locale-info"), "no-intl-numberformat-v3": require("./configs/no-intl-numberformat-v3"), "no-is-usv-string": require("./configs/no-is-usv-string"), "no-iterator-helpers": require("./configs/no-iterator-helpers"), @@ -237,6 +239,14 @@ module.exports = { "no-intl-getcanonicallocales": require("./rules/no-intl-getcanonicallocales"), "no-intl-listformat": require("./rules/no-intl-listformat"), "no-intl-locale": require("./rules/no-intl-locale"), + "no-intl-locale-prototype-firstdayofweek": require("./rules/no-intl-locale-prototype-firstdayofweek"), + "no-intl-locale-prototype-getcalendars": require("./rules/no-intl-locale-prototype-getcalendars"), + "no-intl-locale-prototype-getcollations": require("./rules/no-intl-locale-prototype-getcollations"), + "no-intl-locale-prototype-gethourcycles": require("./rules/no-intl-locale-prototype-gethourcycles"), + "no-intl-locale-prototype-getnumberingsystems": require("./rules/no-intl-locale-prototype-getnumberingsystems"), + "no-intl-locale-prototype-gettextinfo": require("./rules/no-intl-locale-prototype-gettextinfo"), + "no-intl-locale-prototype-gettimezones": require("./rules/no-intl-locale-prototype-gettimezones"), + "no-intl-locale-prototype-getweekinfo": require("./rules/no-intl-locale-prototype-getweekinfo"), "no-intl-numberformat-prototype-formatrange": require("./rules/no-intl-numberformat-prototype-formatrange"), "no-intl-numberformat-prototype-formatrangetoparts": require("./rules/no-intl-numberformat-prototype-formatrangetoparts"), "no-intl-numberformat-prototype-formattoparts": require("./rules/no-intl-numberformat-prototype-formattoparts"), diff --git a/lib/rules/no-intl-locale-prototype-firstdayofweek.js b/lib/rules/no-intl-locale-prototype-firstdayofweek.js new file mode 100644 index 00000000..4fe69b05 --- /dev/null +++ b/lib/rules/no-intl-locale-prototype-firstdayofweek.js @@ -0,0 +1,38 @@ +"use strict" + +const { + definePrototypePropertiesHandler, +} = require("../util/define-prototype-properties-handler") + +module.exports = { + meta: { + docs: { + description: + "disallow the `Intl.Locale.prototype.firstDayOfWeek` property", + category: "ES2026-Intl-API", + proposal: "intl-locale-info", + recommended: false, + url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-intl-locale-prototype-firstdayofweek.html", + }, + fixable: null, + messages: { + forbidden: "ES2026 Intl API '{{name}}' property is forbidden.", + }, + schema: [ + { + type: "object", + properties: { + aggressive: { type: "boolean" }, + allowTestedProperty: { type: "boolean" }, + }, + additionalProperties: false, + }, + ], + type: "problem", + }, + create(context) { + return definePrototypePropertiesHandler(context, { + "Intl.Locale": { firstDayOfWeek: "string" }, + }) + }, +} diff --git a/lib/rules/no-intl-locale-prototype-getcalendars.js b/lib/rules/no-intl-locale-prototype-getcalendars.js new file mode 100644 index 00000000..65ea6a18 --- /dev/null +++ b/lib/rules/no-intl-locale-prototype-getcalendars.js @@ -0,0 +1,38 @@ +"use strict" + +const { + definePrototypePropertiesHandler, +} = require("../util/define-prototype-properties-handler") + +module.exports = { + meta: { + docs: { + description: + "disallow the `Intl.Locale.prototype.getCalendars` method", + category: "ES2026-Intl-API", + proposal: "intl-locale-info", + recommended: false, + url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-intl-locale-prototype-getcalendars.html", + }, + fixable: null, + messages: { + forbidden: "ES2026 Intl API '{{name}}' method is forbidden.", + }, + schema: [ + { + type: "object", + properties: { + aggressive: { type: "boolean" }, + allowTestedProperty: { type: "boolean" }, + }, + additionalProperties: false, + }, + ], + type: "problem", + }, + create(context) { + return definePrototypePropertiesHandler(context, { + "Intl.Locale": { getCalendars: "function" }, + }) + }, +} diff --git a/lib/rules/no-intl-locale-prototype-getcollations.js b/lib/rules/no-intl-locale-prototype-getcollations.js new file mode 100644 index 00000000..a436e076 --- /dev/null +++ b/lib/rules/no-intl-locale-prototype-getcollations.js @@ -0,0 +1,38 @@ +"use strict" + +const { + definePrototypePropertiesHandler, +} = require("../util/define-prototype-properties-handler") + +module.exports = { + meta: { + docs: { + description: + "disallow the `Intl.Locale.prototype.getCollations` method", + category: "ES2026-Intl-API", + proposal: "intl-locale-info", + recommended: false, + url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-intl-locale-prototype-getcollations.html", + }, + fixable: null, + messages: { + forbidden: "ES2026 Intl API '{{name}}' method is forbidden.", + }, + schema: [ + { + type: "object", + properties: { + aggressive: { type: "boolean" }, + allowTestedProperty: { type: "boolean" }, + }, + additionalProperties: false, + }, + ], + type: "problem", + }, + create(context) { + return definePrototypePropertiesHandler(context, { + "Intl.Locale": { getCollations: "function" }, + }) + }, +} diff --git a/lib/rules/no-intl-locale-prototype-gethourcycles.js b/lib/rules/no-intl-locale-prototype-gethourcycles.js new file mode 100644 index 00000000..14c93cdb --- /dev/null +++ b/lib/rules/no-intl-locale-prototype-gethourcycles.js @@ -0,0 +1,38 @@ +"use strict" + +const { + definePrototypePropertiesHandler, +} = require("../util/define-prototype-properties-handler") + +module.exports = { + meta: { + docs: { + description: + "disallow the `Intl.Locale.prototype.getHourCycles` method", + category: "ES2026-Intl-API", + proposal: "intl-locale-info", + recommended: false, + url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-intl-locale-prototype-gethourcycles.html", + }, + fixable: null, + messages: { + forbidden: "ES2026 Intl API '{{name}}' method is forbidden.", + }, + schema: [ + { + type: "object", + properties: { + aggressive: { type: "boolean" }, + allowTestedProperty: { type: "boolean" }, + }, + additionalProperties: false, + }, + ], + type: "problem", + }, + create(context) { + return definePrototypePropertiesHandler(context, { + "Intl.Locale": { getHourCycles: "function" }, + }) + }, +} diff --git a/lib/rules/no-intl-locale-prototype-getnumberingsystems.js b/lib/rules/no-intl-locale-prototype-getnumberingsystems.js new file mode 100644 index 00000000..6f56fd22 --- /dev/null +++ b/lib/rules/no-intl-locale-prototype-getnumberingsystems.js @@ -0,0 +1,38 @@ +"use strict" + +const { + definePrototypePropertiesHandler, +} = require("../util/define-prototype-properties-handler") + +module.exports = { + meta: { + docs: { + description: + "disallow the `Intl.Locale.prototype.getNumberingSystems` method", + category: "ES2026-Intl-API", + proposal: "intl-locale-info", + recommended: false, + url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-intl-locale-prototype-getnumberingsystems.html", + }, + fixable: null, + messages: { + forbidden: "ES2026 Intl API '{{name}}' method is forbidden.", + }, + schema: [ + { + type: "object", + properties: { + aggressive: { type: "boolean" }, + allowTestedProperty: { type: "boolean" }, + }, + additionalProperties: false, + }, + ], + type: "problem", + }, + create(context) { + return definePrototypePropertiesHandler(context, { + "Intl.Locale": { getNumberingSystems: "function" }, + }) + }, +} diff --git a/lib/rules/no-intl-locale-prototype-gettextinfo.js b/lib/rules/no-intl-locale-prototype-gettextinfo.js new file mode 100644 index 00000000..5e17ba30 --- /dev/null +++ b/lib/rules/no-intl-locale-prototype-gettextinfo.js @@ -0,0 +1,38 @@ +"use strict" + +const { + definePrototypePropertiesHandler, +} = require("../util/define-prototype-properties-handler") + +module.exports = { + meta: { + docs: { + description: + "disallow the `Intl.Locale.prototype.getTextInfo` method", + category: "ES2026-Intl-API", + proposal: "intl-locale-info", + recommended: false, + url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-intl-locale-prototype-gettextinfo.html", + }, + fixable: null, + messages: { + forbidden: "ES2026 Intl API '{{name}}' method is forbidden.", + }, + schema: [ + { + type: "object", + properties: { + aggressive: { type: "boolean" }, + allowTestedProperty: { type: "boolean" }, + }, + additionalProperties: false, + }, + ], + type: "problem", + }, + create(context) { + return definePrototypePropertiesHandler(context, { + "Intl.Locale": { getTextInfo: "function" }, + }) + }, +} diff --git a/lib/rules/no-intl-locale-prototype-gettimezones.js b/lib/rules/no-intl-locale-prototype-gettimezones.js new file mode 100644 index 00000000..e43af5d4 --- /dev/null +++ b/lib/rules/no-intl-locale-prototype-gettimezones.js @@ -0,0 +1,38 @@ +"use strict" + +const { + definePrototypePropertiesHandler, +} = require("../util/define-prototype-properties-handler") + +module.exports = { + meta: { + docs: { + description: + "disallow the `Intl.Locale.prototype.getTimeZones` method", + category: "ES2026-Intl-API", + proposal: "intl-locale-info", + recommended: false, + url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-intl-locale-prototype-gettimezones.html", + }, + fixable: null, + messages: { + forbidden: "ES2026 Intl API '{{name}}' method is forbidden.", + }, + schema: [ + { + type: "object", + properties: { + aggressive: { type: "boolean" }, + allowTestedProperty: { type: "boolean" }, + }, + additionalProperties: false, + }, + ], + type: "problem", + }, + create(context) { + return definePrototypePropertiesHandler(context, { + "Intl.Locale": { getTimeZones: "function" }, + }) + }, +} diff --git a/lib/rules/no-intl-locale-prototype-getweekinfo.js b/lib/rules/no-intl-locale-prototype-getweekinfo.js new file mode 100644 index 00000000..615816ab --- /dev/null +++ b/lib/rules/no-intl-locale-prototype-getweekinfo.js @@ -0,0 +1,38 @@ +"use strict" + +const { + definePrototypePropertiesHandler, +} = require("../util/define-prototype-properties-handler") + +module.exports = { + meta: { + docs: { + description: + "disallow the `Intl.Locale.prototype.getWeekInfo` method", + category: "ES2026-Intl-API", + proposal: "intl-locale-info", + recommended: false, + url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-intl-locale-prototype-getweekinfo.html", + }, + fixable: null, + messages: { + forbidden: "ES2026 Intl API '{{name}}' method is forbidden.", + }, + schema: [ + { + type: "object", + properties: { + aggressive: { type: "boolean" }, + allowTestedProperty: { type: "boolean" }, + }, + additionalProperties: false, + }, + ], + type: "problem", + }, + create(context) { + return definePrototypePropertiesHandler(context, { + "Intl.Locale": { getWeekInfo: "function" }, + }) + }, +} diff --git a/lib/util/well-known-properties.js b/lib/util/well-known-properties.js index e57adfa4..e41e9971 100644 --- a/lib/util/well-known-properties.js +++ b/lib/util/well-known-properties.js @@ -1143,6 +1143,15 @@ const intlLocalePrototypeProperties = new Set([ "language", "script", "region", + + "firstDayOfWeek", + "getCalendars", + "getCollations", + "getHourCycles", + "getNumberingSystems", + "getTimeZones", + "getTextInfo", + "getWeekInfo", ]) const intlNumberFormatProperties = new Set([ diff --git a/scripts/new-rule.js b/scripts/new-rule.js index c33f755b..add4e674 100644 --- a/scripts/new-rule.js +++ b/scripts/new-rule.js @@ -21,6 +21,7 @@ main( ) // main +// eslint-disable-next-line complexity async function main(ruleId) { if (ruleId == null) { logger.error("Usage: npm run new ") @@ -52,10 +53,10 @@ async function main(ruleId) { value: "static-properties", label: "The rule forbids the use of static properties.", }, - // { - // value: "prototype-properties", - // label: "The rule forbids the use of prototype properties.", - // }, + { + value: "prototype-properties", + label: "The rule forbids the use of prototype properties.", + }, { value: "nonstandard-static-properties", label: "The rule forbids the use of non-standard static properties.", @@ -77,6 +78,7 @@ async function main(ruleId) { kind, object: "", properties: /** @type {string[]} */ [], + link: "", } if ( @@ -86,22 +88,31 @@ async function main(ruleId) { kind === "nonstandard-static-properties" || kind === "nonstandard-prototype-properties" ) { + const checkTarget = + kind === "global-object" || + kind === "static-properties" || + kind === "nonstandard-static-properties" + ? "global object" + : "instance" resourceOptions.object = await unwrapPrompt( prompts.text({ - message: "What is the global object that the rule checks?", + message: `What is the ${checkTarget} that the rule checks?`, placeholder: "e.g. Set, Map, Math", validate(value) { if (value.trim().length === 0) { - return "The global object name must not be empty." + return `The ${checkTarget} name must not be empty.` } return undefined }, }), ) + resourceOptions.object = + resourceOptions.object[0].toUpperCase() + + resourceOptions.object.slice(1) } if (kind === "static-properties" || kind === "prototype-properties") { - const promptObject = globalThis[resourceOptions.object] + const promptObject = getGlobalObject(resourceOptions.object) const promptProperties = promptObject ? kind === "static-properties" ? Object.getOwnPropertyNames(promptObject) @@ -135,6 +146,7 @@ async function main(ruleId) { const BUILDERS = { "global-object": buildGlobalObjectRuleResources, "static-properties": buildStaticPropertiesRuleResources, + "prototype-properties": buildPrototypePropertiesRuleResources, "nonstandard-static-properties": buildNonStandardStaticPropertiesRuleResources, "nonstandard-prototype-properties": @@ -142,6 +154,25 @@ async function main(ruleId) { default: buildDefaultResources, } + if ( + kind === "global-object" || + kind === "static-properties" || + kind === "prototype-properties" + ) { + resourceOptions.link = await unwrapPrompt( + prompts.text({ + message: "The link that describes the API", + placeholder: "e.g. https://github.com/tc39/proposal-x", + validate(value) { + if (value.trim().length === 0) { + return "The link must not be empty." + } + return undefined + }, + }), + ) + } + const resources = BUILDERS[kind]?.(resourceOptions) ?? buildDefaultResources(resourceOptions) @@ -190,7 +221,8 @@ async function unwrapPrompt(maybeCancelPromise) { return result } -function buildGlobalObjectRuleResources({ ruleId, object }) { +function buildGlobalObjectRuleResources({ ruleId, object, link }) { + const intl = object.startsWith("Intl.") return { rule: `"use strict" @@ -200,13 +232,13 @@ module.exports = { meta: { docs: { description: "disallow the \`${object}\` class.", - category: "ES${maxESVersion}", + category: "ES${maxESVersion}${intl ? "-Intl-API" : ""}", recommended: false, url: "", }, fixable: null, messages: { - forbidden: "ES${maxESVersion} '{{name}}' class is forbidden.", + forbidden: "ES${maxESVersion}${intl ? " Intl API" : ""} '{{name}}' class is forbidden.", }, schema: [], type: "problem", @@ -226,11 +258,11 @@ new RuleTester().run("${ruleId}", rule, { invalid: [ { code: "${object}", - errors: ["ES${maxESVersion} '${object}' class is forbidden."], + errors: ["ES${maxESVersion}${intl ? " Intl API" : ""} '${object}' class is forbidden."], }, { code: "function f() { ${object} }", - errors: ["ES${maxESVersion} '${object}' class is forbidden."], + errors: ["ES${maxESVersion}${intl ? " Intl API" : ""} '${object}' class is forbidden."], }, ], }) @@ -238,7 +270,7 @@ new RuleTester().run("${ruleId}", rule, { doc: `# es-x/${ruleId} > -This rule reports ES${maxESVersion} [\`${object}\` class]($$LINK$$) as errors. +This rule reports ES${maxESVersion}${intl ? " Intl API" : ""} [\`${object}\` class](${link}) as errors. ## 💡 Examples @@ -256,8 +288,14 @@ let ${object.toLowerCase()} = new ${object}() } } -function buildStaticPropertiesRuleResources({ ruleId, object, properties }) { - const promptObject = globalThis[object] +function buildStaticPropertiesRuleResources({ + ruleId, + object, + properties, + link, +}) { + const intl = object.startsWith("Intl.") + const promptObject = getGlobalObject(object) const exampleProperty = promptObject ? Object.getOwnPropertyNames(promptObject)[0] : "example" @@ -291,13 +329,13 @@ module.exports = { meta: { docs: { description: "disallow the \`${object}.${propertiesString}\` ${kind[0]}", - category: "ES${maxESVersion}", + category: "ES${maxESVersion}${intl ? "-Intl-API" : ""}", recommended: false, url: "", }, fixable: null, messages: { - forbidden: "ES${maxESVersion} '{{name}}' ${kind[0]} is forbidden.", + forbidden: "ES${maxESVersion}${intl ? " Intl API" : ""} '{{name}}' ${kind[0]} is forbidden.", }, schema: [ { @@ -333,7 +371,7 @@ new RuleTester().run("${ruleId}", rule, { .map( (p) => `{ code: "${object}.${p}", - errors: ["ES${maxESVersion} '${object}.${p}' ${kind[0]} is forbidden."], + errors: ["ES${maxESVersion}${intl ? " Intl API" : ""} '${object}.${p}' ${kind[0]} is forbidden."], }`, ) .join(",\n")} @@ -343,7 +381,7 @@ new RuleTester().run("${ruleId}", rule, { doc: `# es-x/${ruleId} > -This rule reports ES${maxESVersion} [${propertiesName}]($$LINK$$) as errors. +This rule reports ES${maxESVersion}${intl ? " Intl API" : ""} [${propertiesName}](${link}) as errors. ## 💡 Examples @@ -383,6 +421,276 @@ This is prior to the \`settings['es-x'].allowTestedProperty\` setting. } } +function buildPrototypePropertiesRuleResources({ + ruleId, + object, + properties, + link, +}) { + const intl = object.startsWith("Intl.") + const promptInstancePrototype = getGlobalObject(object)?.prototype + let propertyType = "undefined" + try { + propertyType = promptInstancePrototype + ? typeof promptInstancePrototype[properties[0]] + : "function" + } catch { + // ignore + } + const exampleProperty = promptInstancePrototype + ? Object.getOwnPropertyNames(promptInstancePrototype).find((nm) => { + if (nm === "constructor") { + return false + } + if (propertyType === "function") { + try { + return typeof promptInstancePrototype[nm] === "function" + } catch { + return false + } + } + return true + }) + : "example" + const kind = + propertyType === "function" + ? ["method", "methods"] + : ["property", "properties"] + const propertiesString = + properties.length > 1 ? `{${properties.join(",")}}` : properties[0] + let propertiesName = `\`${object}.prototype.${properties[properties.length - 1]}\` ${kind[0]}` + if (properties.length > 1) { + propertiesName = `${properties + .slice(0, -1) + .map((p) => `\`${object}.prototype.${p}\``) + .join( + ", ", + )}, and \`${object}.prototype.${properties[properties.length - 1]}\` ${kind[1]}` + } + + return { + rule: `"use strict" + +const { + definePrototypePropertiesHandler, +} = require("../util/define-prototype-properties-handler") + +module.exports = { + meta: { + docs: { + description: "disallow the \`${object}.prototype.${propertiesString}\` ${kind[0]}", + category: "ES${maxESVersion}${intl ? "-Intl-API" : ""}", + recommended: false, + url: "", + }, + fixable: null, + messages: { + forbidden: "ES${maxESVersion}${intl ? " Intl API" : ""} '{{name}}' ${kind[0]} is forbidden.", + }, + schema: [ + { + type: "object", + properties: { + aggressive: { type: "boolean" }, + allowTestedProperty: { type: "boolean" }, + }, + additionalProperties: false, + }, + ], + type: "problem", + }, + create(context) { + return definePrototypePropertiesHandler(context, { + "${object}": { ${properties.map((p) => `"${p}": "${propertyType}"`).join(",\n")} }, + }) + }, +} +`, + test: `"use strict" + +const path = require("path") +const RuleTester = require("../../tester") +const rule = require("../../../lib/rules/${ruleId}.js") +const ruleId = "${ruleId}" + +new RuleTester().run(ruleId, rule, { + valid: [ + ${properties.map((p) => `"${p}${propertyType === "function" ? "()" : ""}"`).join(",\n")}, + ${properties.map((p) => `"foo.${p}${propertyType === "function" ? "()" : ""}"`).join(",\n")}, + ${properties.map((p) => `{ code: "${p}${propertyType === "function" ? "()" : ""}", settings: { "es-x": { aggressive: true } } }`).join(",\n")}, + { code: "foo.${exampleProperty}${propertyType === "function" ? "()" : ""}", settings: { "es-x": { aggressive: true } } }, + ${properties + .map( + (p) => `{ + code: "foo.${p}${propertyType === "function" ? "()" : ""}", + options: [{ aggressive: false }], + settings: { "es-x": { aggressive: true } } + }`, + ) + .join(",\n")}, + ], + invalid: [ + ${properties + .map( + (p) => `{ + code: "foo.${p}${propertyType === "function" ? "()" : ""}", + errors: ["ES${maxESVersion}${intl ? " Intl API" : ""} '${object}.prototype.${p}' ${kind[0]} is forbidden."], + settings: { "es-x": { aggressive: true } }, + }`, + ) + .join(",\n")}, + ${properties + .map( + (p) => `{ + code: "foo.${p}${propertyType === "function" ? "()" : ""}", + options: [{ aggressive: true }], + errors: ["ES${maxESVersion}${intl ? " Intl API" : ""} '${object}.prototype.${p}' ${kind[0]} is forbidden."], + settings: { "es-x": { aggressive: false } }, + }`, + ) + .join(",\n")}, + ${properties + .map( + (p) => `{ + code: "const foo = new ${object}(); foo.${p}${propertyType === "function" ? "()" : ""}", + errors: ["ES${maxESVersion}${intl ? " Intl API" : ""} '${object}.prototype.${p}' ${kind[0]} is forbidden."], + }`, + ) + .join(",\n")}, + ], +}) + + + +// ----------------------------------------------------------------------------- +// TypeScript +// ----------------------------------------------------------------------------- +const parser = require("@typescript-eslint/parser") +const tsconfigRootDir = path.resolve(__dirname, "../../fixtures") +const project = "tsconfig.json" +const filename = path.join(tsconfigRootDir, "test.ts") + +new RuleTester({ + languageOptions: { + parser, + parserOptions: { + tsconfigRootDir, + project, + disallowAutomaticSingleRunInference: true, + }, + }, +}).run(\`\${ruleId} TS Full Type Information\`, rule, { + valid: [ + ${properties.map((p) => `{ filename, code: "${p}${propertyType === "function" ? "()" : ""}"}`).join(",\n")}, + { filename, code: "foo.${exampleProperty}${propertyType === "function" ? "()" : ""}"}, + ${properties.map((p) => `{ filename, code: "foo.${p}${propertyType === "function" ? "()" : ""}"}`).join(",\n")}, + ${properties.map((p) => `{ filename, code: "let foo = {}; foo.${p}${propertyType === "function" ? "()" : ""}"}`).join(",\n")}, + ${properties + .map( + (p) => `{ + filename, + code: "${p}${propertyType === "function" ? "()" : ""}", + settings: { "es-x": { aggressive: true } }, + }`, + ) + .join(",\n")}, + { + filename, + code: "foo.${exampleProperty}${propertyType === "function" ? "()" : ""}", + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + ${properties + .map( + (p) => `{ + filename, + code: "(new ${object}()).${p}${propertyType === "function" ? "()" : ""}", + errors: ["ES${maxESVersion}${intl ? " Intl API" : ""} '${object}.prototype.${p}' ${kind[0]} is forbidden."], + }`, + ) + .join(",\n")}, + ${properties + .map( + (p) => `{ + filename, + code: "let foo = new ${object}(); foo.${p}${propertyType === "function" ? "()" : ""}", + errors: ["ES${maxESVersion}${intl ? " Intl API" : ""} '${object}.prototype.${p}' ${kind[0]} is forbidden."], + }`, + ) + .join(",\n")}, + ${properties + .map( + (p) => `{ + filename, + code: "function f(a: T) { a.${p}${propertyType === "function" ? "()" : ""} }", + errors: ["ES${maxESVersion}${intl ? " Intl API" : ""} '${object}.prototype.${p}' ${kind[0]} is forbidden."], + }`, + ) + .join(",\n")}, + ${properties + .map( + (p) => `{ + filename, + code: "foo.${p}${propertyType === "function" ? "()" : ""}", + errors: ["ES${maxESVersion}${intl ? " Intl API" : ""} '${object}.prototype.${p}' ${kind[0]} is forbidden."], + settings: { "es-x": { aggressive: true } }, + }`, + ) + .join(",\n")}, + ], +}) +`, + doc: `# es-x/${ruleId} +> + +This rule reports ES${maxESVersion}${intl ? " Intl API" : ""} [${propertiesName}](${link}) as errors. + +## 💡 Examples + +⛔ Examples of **incorrect** code for this rule: + + + +\`\`\`js +/*eslint es-x/${ruleId}: error */ +const foo = new ${object}(); +${properties.map((p) => `foo.${p}${propertyType === "function" ? "()" : ""};`).join("\n")} +\`\`\` + + + +## 🔧 Options + +This rule has an option. + +\`\`\`jsonc +{ + "rules": { + "es-x/${ruleId}": [ + "error", + { + "aggressive": false, + "allowTestedProperty": false + } + ] + } +} +\`\`\` + +### aggressive: boolean + +Configure the aggressive mode for only this rule. +This is prior to the \`settings['es-x'].aggressive\` setting. + +### allowTestedProperty: boolean + +Configure the allowTestedProperty mode for only this rule. +This is prior to the \`settings['es-x'].allowTestedProperty\` setting. +`, + } +} + function buildNonStandardStaticPropertiesRuleResources({ ruleId, object }) { const camelObject = camelCase(object) return { @@ -724,7 +1032,7 @@ module.exports = { meta: { docs: { description: "disallow ....", - category: "ES${maxESVersion}", + category: "ES${maxESVersion}${ruleId.startsWith("no-intl-") ? "-Intl-API" : ""}", recommended: false, url: "", }, @@ -783,3 +1091,14 @@ function camelCase(str) { : str return `${base[0].toLowerCase()}${base.slice(1)}` } + +function getGlobalObject(object) { + let target = globalThis + for (const part of object.split(".")) { + if (target[part] == null) { + return null + } + target = target[part] + } + return target +} diff --git a/scripts/proposals.js b/scripts/proposals.js index bde6cdfb..4b4ee3c9 100644 --- a/scripts/proposals.js +++ b/scripts/proposals.js @@ -25,6 +25,10 @@ module.exports = { title: "Import Attributes", link: "https://github.com/tc39/proposal-import-attributes", }, + "intl-locale-info": { + title: "Intl Locale Info API", + link: "https://github.com/tc39/proposal-intl-locale-info", + }, "intl-numberformat-v3": { title: "Intl.NumberFormat V3", link: "https://github.com/tc39/proposal-intl-numberformat-v3", diff --git a/tests/lib/rules/no-intl-locale-prototype-firstdayofweek.js b/tests/lib/rules/no-intl-locale-prototype-firstdayofweek.js new file mode 100644 index 00000000..84ae35f7 --- /dev/null +++ b/tests/lib/rules/no-intl-locale-prototype-firstdayofweek.js @@ -0,0 +1,110 @@ +"use strict" + +const path = require("path") +const RuleTester = require("../../tester") +const rule = require("../../../lib/rules/no-intl-locale-prototype-firstdayofweek.js") +const ruleId = "no-intl-locale-prototype-firstdayofweek" + +new RuleTester().run(ruleId, rule, { + valid: [ + "firstDayOfWeek", + "foo.firstDayOfWeek", + { code: "firstDayOfWeek", settings: { "es-x": { aggressive: true } } }, + { code: "foo.constructor", settings: { "es-x": { aggressive: true } } }, + { + code: "foo.firstDayOfWeek", + options: [{ aggressive: false }], + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + { + code: "foo.firstDayOfWeek", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.firstDayOfWeek' property is forbidden.", + ], + settings: { "es-x": { aggressive: true } }, + }, + { + code: "foo.firstDayOfWeek", + options: [{ aggressive: true }], + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.firstDayOfWeek' property is forbidden.", + ], + settings: { "es-x": { aggressive: false } }, + }, + { + code: "const foo = new Intl.Locale(); foo.firstDayOfWeek", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.firstDayOfWeek' property is forbidden.", + ], + }, + ], +}) + +// ----------------------------------------------------------------------------- +// TypeScript +// ----------------------------------------------------------------------------- +const parser = require("@typescript-eslint/parser") +const tsconfigRootDir = path.resolve(__dirname, "../../fixtures") +const project = "tsconfig.json" +const filename = path.join(tsconfigRootDir, "test.ts") + +new RuleTester({ + languageOptions: { + parser, + parserOptions: { + tsconfigRootDir, + project, + disallowAutomaticSingleRunInference: true, + }, + }, +}).run(`${ruleId} TS Full Type Information`, rule, { + valid: [ + { filename, code: "firstDayOfWeek" }, + { filename, code: "foo.constructor" }, + { filename, code: "foo.firstDayOfWeek" }, + { filename, code: "let foo = {}; foo.firstDayOfWeek" }, + { + filename, + code: "firstDayOfWeek", + settings: { "es-x": { aggressive: true } }, + }, + { + filename, + code: "foo.constructor", + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + { + filename, + code: "(new Intl.Locale()).firstDayOfWeek", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.firstDayOfWeek' property is forbidden.", + ], + }, + { + filename, + code: "let foo = new Intl.Locale(); foo.firstDayOfWeek", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.firstDayOfWeek' property is forbidden.", + ], + }, + { + filename, + code: "function f(a: T) { a.firstDayOfWeek }", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.firstDayOfWeek' property is forbidden.", + ], + }, + { + filename, + code: "foo.firstDayOfWeek", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.firstDayOfWeek' property is forbidden.", + ], + settings: { "es-x": { aggressive: true } }, + }, + ], +}) diff --git a/tests/lib/rules/no-intl-locale-prototype-getcalendars.js b/tests/lib/rules/no-intl-locale-prototype-getcalendars.js new file mode 100644 index 00000000..83bf45f8 --- /dev/null +++ b/tests/lib/rules/no-intl-locale-prototype-getcalendars.js @@ -0,0 +1,113 @@ +"use strict" + +const path = require("path") +const RuleTester = require("../../tester") +const rule = require("../../../lib/rules/no-intl-locale-prototype-getcalendars.js") +const ruleId = "no-intl-locale-prototype-getcalendars" + +new RuleTester().run(ruleId, rule, { + valid: [ + "getCalendars()", + "foo.getCalendars()", + { code: "getCalendars()", settings: { "es-x": { aggressive: true } } }, + { + code: "foo.toString()", + settings: { "es-x": { aggressive: true } }, + }, + { + code: "foo.getCalendars()", + options: [{ aggressive: false }], + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + { + code: "foo.getCalendars()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getCalendars' method is forbidden.", + ], + settings: { "es-x": { aggressive: true } }, + }, + { + code: "foo.getCalendars()", + options: [{ aggressive: true }], + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getCalendars' method is forbidden.", + ], + settings: { "es-x": { aggressive: false } }, + }, + { + code: "const foo = new Intl.Locale(); foo.getCalendars()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getCalendars' method is forbidden.", + ], + }, + ], +}) + +// ----------------------------------------------------------------------------- +// TypeScript +// ----------------------------------------------------------------------------- +const parser = require("@typescript-eslint/parser") +const tsconfigRootDir = path.resolve(__dirname, "../../fixtures") +const project = "tsconfig.json" +const filename = path.join(tsconfigRootDir, "test.ts") + +new RuleTester({ + languageOptions: { + parser, + parserOptions: { + tsconfigRootDir, + project, + disallowAutomaticSingleRunInference: true, + }, + }, +}).run(`${ruleId} TS Full Type Information`, rule, { + valid: [ + { filename, code: "getCalendars()" }, + { filename, code: "foo.toString()" }, + { filename, code: "foo.getCalendars()" }, + { filename, code: "let foo = {}; foo.getCalendars()" }, + { + filename, + code: "getCalendars()", + settings: { "es-x": { aggressive: true } }, + }, + { + filename, + code: "foo.toString()", + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + { + filename, + code: "(new Intl.Locale()).getCalendars()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getCalendars' method is forbidden.", + ], + }, + { + filename, + code: "let foo = new Intl.Locale(); foo.getCalendars()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getCalendars' method is forbidden.", + ], + }, + { + filename, + code: "function f(a: T) { a.getCalendars() }", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getCalendars' method is forbidden.", + ], + }, + { + filename, + code: "foo.getCalendars()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getCalendars' method is forbidden.", + ], + settings: { "es-x": { aggressive: true } }, + }, + ], +}) diff --git a/tests/lib/rules/no-intl-locale-prototype-getcollations.js b/tests/lib/rules/no-intl-locale-prototype-getcollations.js new file mode 100644 index 00000000..d36c1e9e --- /dev/null +++ b/tests/lib/rules/no-intl-locale-prototype-getcollations.js @@ -0,0 +1,113 @@ +"use strict" + +const path = require("path") +const RuleTester = require("../../tester") +const rule = require("../../../lib/rules/no-intl-locale-prototype-getcollations.js") +const ruleId = "no-intl-locale-prototype-getcollations" + +new RuleTester().run(ruleId, rule, { + valid: [ + "getCollations()", + "foo.getCollations()", + { code: "getCollations()", settings: { "es-x": { aggressive: true } } }, + { + code: "foo.toString()", + settings: { "es-x": { aggressive: true } }, + }, + { + code: "foo.getCollations()", + options: [{ aggressive: false }], + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + { + code: "foo.getCollations()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getCollations' method is forbidden.", + ], + settings: { "es-x": { aggressive: true } }, + }, + { + code: "foo.getCollations()", + options: [{ aggressive: true }], + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getCollations' method is forbidden.", + ], + settings: { "es-x": { aggressive: false } }, + }, + { + code: "const foo = new Intl.Locale(); foo.getCollations()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getCollations' method is forbidden.", + ], + }, + ], +}) + +// ----------------------------------------------------------------------------- +// TypeScript +// ----------------------------------------------------------------------------- +const parser = require("@typescript-eslint/parser") +const tsconfigRootDir = path.resolve(__dirname, "../../fixtures") +const project = "tsconfig.json" +const filename = path.join(tsconfigRootDir, "test.ts") + +new RuleTester({ + languageOptions: { + parser, + parserOptions: { + tsconfigRootDir, + project, + disallowAutomaticSingleRunInference: true, + }, + }, +}).run(`${ruleId} TS Full Type Information`, rule, { + valid: [ + { filename, code: "getCollations()" }, + { filename, code: "foo.toString()" }, + { filename, code: "foo.getCollations()" }, + { filename, code: "let foo = {}; foo.getCollations()" }, + { + filename, + code: "getCollations()", + settings: { "es-x": { aggressive: true } }, + }, + { + filename, + code: "foo.toString()", + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + { + filename, + code: "(new Intl.Locale()).getCollations()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getCollations' method is forbidden.", + ], + }, + { + filename, + code: "let foo = new Intl.Locale(); foo.getCollations()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getCollations' method is forbidden.", + ], + }, + { + filename, + code: "function f(a: T) { a.getCollations() }", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getCollations' method is forbidden.", + ], + }, + { + filename, + code: "foo.getCollations()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getCollations' method is forbidden.", + ], + settings: { "es-x": { aggressive: true } }, + }, + ], +}) diff --git a/tests/lib/rules/no-intl-locale-prototype-gethourcycles.js b/tests/lib/rules/no-intl-locale-prototype-gethourcycles.js new file mode 100644 index 00000000..9faa02df --- /dev/null +++ b/tests/lib/rules/no-intl-locale-prototype-gethourcycles.js @@ -0,0 +1,113 @@ +"use strict" + +const path = require("path") +const RuleTester = require("../../tester") +const rule = require("../../../lib/rules/no-intl-locale-prototype-gethourcycles.js") +const ruleId = "no-intl-locale-prototype-gethourcycles" + +new RuleTester().run(ruleId, rule, { + valid: [ + "getHourCycles()", + "foo.getHourCycles()", + { code: "getHourCycles()", settings: { "es-x": { aggressive: true } } }, + { + code: "foo.toString()", + settings: { "es-x": { aggressive: true } }, + }, + { + code: "foo.getHourCycles()", + options: [{ aggressive: false }], + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + { + code: "foo.getHourCycles()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getHourCycles' method is forbidden.", + ], + settings: { "es-x": { aggressive: true } }, + }, + { + code: "foo.getHourCycles()", + options: [{ aggressive: true }], + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getHourCycles' method is forbidden.", + ], + settings: { "es-x": { aggressive: false } }, + }, + { + code: "const foo = new Intl.Locale(); foo.getHourCycles()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getHourCycles' method is forbidden.", + ], + }, + ], +}) + +// ----------------------------------------------------------------------------- +// TypeScript +// ----------------------------------------------------------------------------- +const parser = require("@typescript-eslint/parser") +const tsconfigRootDir = path.resolve(__dirname, "../../fixtures") +const project = "tsconfig.json" +const filename = path.join(tsconfigRootDir, "test.ts") + +new RuleTester({ + languageOptions: { + parser, + parserOptions: { + tsconfigRootDir, + project, + disallowAutomaticSingleRunInference: true, + }, + }, +}).run(`${ruleId} TS Full Type Information`, rule, { + valid: [ + { filename, code: "getHourCycles()" }, + { filename, code: "foo.toString()" }, + { filename, code: "foo.getHourCycles()" }, + { filename, code: "let foo = {}; foo.getHourCycles()" }, + { + filename, + code: "getHourCycles()", + settings: { "es-x": { aggressive: true } }, + }, + { + filename, + code: "foo.toString()", + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + { + filename, + code: "(new Intl.Locale()).getHourCycles()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getHourCycles' method is forbidden.", + ], + }, + { + filename, + code: "let foo = new Intl.Locale(); foo.getHourCycles()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getHourCycles' method is forbidden.", + ], + }, + { + filename, + code: "function f(a: T) { a.getHourCycles() }", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getHourCycles' method is forbidden.", + ], + }, + { + filename, + code: "foo.getHourCycles()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getHourCycles' method is forbidden.", + ], + settings: { "es-x": { aggressive: true } }, + }, + ], +}) diff --git a/tests/lib/rules/no-intl-locale-prototype-getnumberingsystems.js b/tests/lib/rules/no-intl-locale-prototype-getnumberingsystems.js new file mode 100644 index 00000000..e48506a5 --- /dev/null +++ b/tests/lib/rules/no-intl-locale-prototype-getnumberingsystems.js @@ -0,0 +1,116 @@ +"use strict" + +const path = require("path") +const RuleTester = require("../../tester") +const rule = require("../../../lib/rules/no-intl-locale-prototype-getnumberingsystems.js") +const ruleId = "no-intl-locale-prototype-getnumberingsystems" + +new RuleTester().run(ruleId, rule, { + valid: [ + "getNumberingSystems()", + "foo.getNumberingSystems()", + { + code: "getNumberingSystems()", + settings: { "es-x": { aggressive: true } }, + }, + { + code: "foo.toString()", + settings: { "es-x": { aggressive: true } }, + }, + { + code: "foo.getNumberingSystems()", + options: [{ aggressive: false }], + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + { + code: "foo.getNumberingSystems()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getNumberingSystems' method is forbidden.", + ], + settings: { "es-x": { aggressive: true } }, + }, + { + code: "foo.getNumberingSystems()", + options: [{ aggressive: true }], + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getNumberingSystems' method is forbidden.", + ], + settings: { "es-x": { aggressive: false } }, + }, + { + code: "const foo = new Intl.Locale(); foo.getNumberingSystems()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getNumberingSystems' method is forbidden.", + ], + }, + ], +}) + +// ----------------------------------------------------------------------------- +// TypeScript +// ----------------------------------------------------------------------------- +const parser = require("@typescript-eslint/parser") +const tsconfigRootDir = path.resolve(__dirname, "../../fixtures") +const project = "tsconfig.json" +const filename = path.join(tsconfigRootDir, "test.ts") + +new RuleTester({ + languageOptions: { + parser, + parserOptions: { + tsconfigRootDir, + project, + disallowAutomaticSingleRunInference: true, + }, + }, +}).run(`${ruleId} TS Full Type Information`, rule, { + valid: [ + { filename, code: "getNumberingSystems()" }, + { filename, code: "foo.toString()" }, + { filename, code: "foo.getNumberingSystems()" }, + { filename, code: "let foo = {}; foo.getNumberingSystems()" }, + { + filename, + code: "getNumberingSystems()", + settings: { "es-x": { aggressive: true } }, + }, + { + filename, + code: "foo.toString()", + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + { + filename, + code: "(new Intl.Locale()).getNumberingSystems()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getNumberingSystems' method is forbidden.", + ], + }, + { + filename, + code: "let foo = new Intl.Locale(); foo.getNumberingSystems()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getNumberingSystems' method is forbidden.", + ], + }, + { + filename, + code: "function f(a: T) { a.getNumberingSystems() }", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getNumberingSystems' method is forbidden.", + ], + }, + { + filename, + code: "foo.getNumberingSystems()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getNumberingSystems' method is forbidden.", + ], + settings: { "es-x": { aggressive: true } }, + }, + ], +}) diff --git a/tests/lib/rules/no-intl-locale-prototype-gettextinfo.js b/tests/lib/rules/no-intl-locale-prototype-gettextinfo.js new file mode 100644 index 00000000..1288beaf --- /dev/null +++ b/tests/lib/rules/no-intl-locale-prototype-gettextinfo.js @@ -0,0 +1,113 @@ +"use strict" + +const path = require("path") +const RuleTester = require("../../tester") +const rule = require("../../../lib/rules/no-intl-locale-prototype-gettextinfo.js") +const ruleId = "no-intl-locale-prototype-gettextinfo" + +new RuleTester().run(ruleId, rule, { + valid: [ + "getTextInfo()", + "foo.getTextInfo()", + { code: "getTextInfo()", settings: { "es-x": { aggressive: true } } }, + { + code: "foo.toString()", + settings: { "es-x": { aggressive: true } }, + }, + { + code: "foo.getTextInfo()", + options: [{ aggressive: false }], + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + { + code: "foo.getTextInfo()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getTextInfo' method is forbidden.", + ], + settings: { "es-x": { aggressive: true } }, + }, + { + code: "foo.getTextInfo()", + options: [{ aggressive: true }], + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getTextInfo' method is forbidden.", + ], + settings: { "es-x": { aggressive: false } }, + }, + { + code: "const foo = new Intl.Locale(); foo.getTextInfo()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getTextInfo' method is forbidden.", + ], + }, + ], +}) + +// ----------------------------------------------------------------------------- +// TypeScript +// ----------------------------------------------------------------------------- +const parser = require("@typescript-eslint/parser") +const tsconfigRootDir = path.resolve(__dirname, "../../fixtures") +const project = "tsconfig.json" +const filename = path.join(tsconfigRootDir, "test.ts") + +new RuleTester({ + languageOptions: { + parser, + parserOptions: { + tsconfigRootDir, + project, + disallowAutomaticSingleRunInference: true, + }, + }, +}).run(`${ruleId} TS Full Type Information`, rule, { + valid: [ + { filename, code: "getTextInfo()" }, + { filename, code: "foo.toString()" }, + { filename, code: "foo.getTextInfo()" }, + { filename, code: "let foo = {}; foo.getTextInfo()" }, + { + filename, + code: "getTextInfo()", + settings: { "es-x": { aggressive: true } }, + }, + { + filename, + code: "foo.toString()", + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + { + filename, + code: "(new Intl.Locale()).getTextInfo()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getTextInfo' method is forbidden.", + ], + }, + { + filename, + code: "let foo = new Intl.Locale(); foo.getTextInfo()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getTextInfo' method is forbidden.", + ], + }, + { + filename, + code: "function f(a: T) { a.getTextInfo() }", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getTextInfo' method is forbidden.", + ], + }, + { + filename, + code: "foo.getTextInfo()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getTextInfo' method is forbidden.", + ], + settings: { "es-x": { aggressive: true } }, + }, + ], +}) diff --git a/tests/lib/rules/no-intl-locale-prototype-gettimezones.js b/tests/lib/rules/no-intl-locale-prototype-gettimezones.js new file mode 100644 index 00000000..7a6da6a0 --- /dev/null +++ b/tests/lib/rules/no-intl-locale-prototype-gettimezones.js @@ -0,0 +1,113 @@ +"use strict" + +const path = require("path") +const RuleTester = require("../../tester") +const rule = require("../../../lib/rules/no-intl-locale-prototype-gettimezones.js") +const ruleId = "no-intl-locale-prototype-gettimezones" + +new RuleTester().run(ruleId, rule, { + valid: [ + "getTimeZones()", + "foo.getTimeZones()", + { code: "getTimeZones()", settings: { "es-x": { aggressive: true } } }, + { + code: "foo.toString()", + settings: { "es-x": { aggressive: true } }, + }, + { + code: "foo.getTimeZones()", + options: [{ aggressive: false }], + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + { + code: "foo.getTimeZones()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getTimeZones' method is forbidden.", + ], + settings: { "es-x": { aggressive: true } }, + }, + { + code: "foo.getTimeZones()", + options: [{ aggressive: true }], + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getTimeZones' method is forbidden.", + ], + settings: { "es-x": { aggressive: false } }, + }, + { + code: "const foo = new Intl.Locale(); foo.getTimeZones()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getTimeZones' method is forbidden.", + ], + }, + ], +}) + +// ----------------------------------------------------------------------------- +// TypeScript +// ----------------------------------------------------------------------------- +const parser = require("@typescript-eslint/parser") +const tsconfigRootDir = path.resolve(__dirname, "../../fixtures") +const project = "tsconfig.json" +const filename = path.join(tsconfigRootDir, "test.ts") + +new RuleTester({ + languageOptions: { + parser, + parserOptions: { + tsconfigRootDir, + project, + disallowAutomaticSingleRunInference: true, + }, + }, +}).run(`${ruleId} TS Full Type Information`, rule, { + valid: [ + { filename, code: "getTimeZones()" }, + { filename, code: "foo.toString()" }, + { filename, code: "foo.getTimeZones()" }, + { filename, code: "let foo = {}; foo.getTimeZones()" }, + { + filename, + code: "getTimeZones()", + settings: { "es-x": { aggressive: true } }, + }, + { + filename, + code: "foo.toString()", + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + { + filename, + code: "(new Intl.Locale()).getTimeZones()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getTimeZones' method is forbidden.", + ], + }, + { + filename, + code: "let foo = new Intl.Locale(); foo.getTimeZones()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getTimeZones' method is forbidden.", + ], + }, + { + filename, + code: "function f(a: T) { a.getTimeZones() }", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getTimeZones' method is forbidden.", + ], + }, + { + filename, + code: "foo.getTimeZones()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getTimeZones' method is forbidden.", + ], + settings: { "es-x": { aggressive: true } }, + }, + ], +}) diff --git a/tests/lib/rules/no-intl-locale-prototype-getweekinfo.js b/tests/lib/rules/no-intl-locale-prototype-getweekinfo.js new file mode 100644 index 00000000..6eadec80 --- /dev/null +++ b/tests/lib/rules/no-intl-locale-prototype-getweekinfo.js @@ -0,0 +1,110 @@ +"use strict" + +const path = require("path") +const RuleTester = require("../../tester") +const rule = require("../../../lib/rules/no-intl-locale-prototype-getweekinfo.js") +const ruleId = "no-intl-locale-prototype-getweekinfo" + +new RuleTester().run(ruleId, rule, { + valid: [ + "getWeekInfo()", + "foo.getWeekInfo()", + { code: "getWeekInfo()", settings: { "es-x": { aggressive: true } } }, + { code: "foo.toString()", settings: { "es-x": { aggressive: true } } }, + { + code: "foo.getWeekInfo()", + options: [{ aggressive: false }], + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + { + code: "foo.getWeekInfo()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getWeekInfo' method is forbidden.", + ], + settings: { "es-x": { aggressive: true } }, + }, + { + code: "foo.getWeekInfo()", + options: [{ aggressive: true }], + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getWeekInfo' method is forbidden.", + ], + settings: { "es-x": { aggressive: false } }, + }, + { + code: "const foo = new Intl.Locale(); foo.getWeekInfo()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getWeekInfo' method is forbidden.", + ], + }, + ], +}) + +// ----------------------------------------------------------------------------- +// TypeScript +// ----------------------------------------------------------------------------- +const parser = require("@typescript-eslint/parser") +const tsconfigRootDir = path.resolve(__dirname, "../../fixtures") +const project = "tsconfig.json" +const filename = path.join(tsconfigRootDir, "test.ts") + +new RuleTester({ + languageOptions: { + parser, + parserOptions: { + tsconfigRootDir, + project, + disallowAutomaticSingleRunInference: true, + }, + }, +}).run(`${ruleId} TS Full Type Information`, rule, { + valid: [ + { filename, code: "getWeekInfo()" }, + { filename, code: "foo.toString()" }, + { filename, code: "foo.getWeekInfo()" }, + { filename, code: "let foo = {}; foo.getWeekInfo()" }, + { + filename, + code: "getWeekInfo()", + settings: { "es-x": { aggressive: true } }, + }, + { + filename, + code: "foo.toString()", + settings: { "es-x": { aggressive: true } }, + }, + ], + invalid: [ + { + filename, + code: "(new Intl.Locale()).getWeekInfo()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getWeekInfo' method is forbidden.", + ], + }, + { + filename, + code: "let foo = new Intl.Locale(); foo.getWeekInfo()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getWeekInfo' method is forbidden.", + ], + }, + { + filename, + code: "function f(a: T) { a.getWeekInfo() }", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getWeekInfo' method is forbidden.", + ], + }, + { + filename, + code: "foo.getWeekInfo()", + errors: [ + "ES2026 Intl API 'Intl.Locale.prototype.getWeekInfo' method is forbidden.", + ], + settings: { "es-x": { aggressive: true } }, + }, + ], +}) diff --git a/tests/lib/util/well-known-properties.js b/tests/lib/util/well-known-properties.js index 7a2272bf..c250abbd 100644 --- a/tests/lib/util/well-known-properties.js +++ b/tests/lib/util/well-known-properties.js @@ -675,7 +675,16 @@ function* getAllProperties(object) { object === Function.prototype) || (key === "stack" && object instanceof Error) || ((key === "prepareStackTrace" || key === "stackTraceLimit") && - object === Error) + object === Error) || + // https://github.com/tc39/proposal-intl-locale-info/pull/67 + ((key === "calendars" || + key === "collations" || + key === "hourCycles" || + key === "numberingSystems" || + key === "textInfo" || + key === "timeZones" || + key === "weekInfo") && + object === Intl.Locale.prototype) ) { // Skip Non-standard property continue @@ -686,24 +695,7 @@ function* getAllProperties(object) { // https://github.com/tc39/proposal-error-capturestacktrace (key === "captureStackTrace" && object === Error) || // https://github.com/tc39/proposal-json-parse-with-source - ((key === "rawJSON" || key === "isRawJSON") && object === JSON) || - // https://github.com/tc39/proposal-intl-locale-info - ((key === "firstDayOfWeek" || - key === "getCalendars" || - key === "getCollations" || - key === "getHourCycles" || - key === "getNumberingSystems" || - key === "getTimeZones" || - key === "getTextInfo" || - key === "getWeekInfo" || - key === "calendars" || - key === "collations" || - key === "hourCycles" || - key === "numberingSystems" || - key === "textInfo" || - key === "timeZones" || - key === "weekInfo") && - object === Intl.Locale.prototype) + ((key === "rawJSON" || key === "isRawJSON") && object === JSON) ) { // Skip ESNext property continue