diff --git a/docs/configs/index.md b/docs/configs/index.md index dfd2cdd3..7eb6099f 100644 --- a/docs/configs/index.md +++ b/docs/configs/index.md @@ -28,6 +28,32 @@ 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. + +### [Config (Flat Config)] + +eslint.config.js: + +```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-es2024 disallow new stuff in ES2024. diff --git a/docs/rules/index.md b/docs/rules/index.md index 59a69421..c5d0f97e 100644 --- a/docs/rules/index.md +++ b/docs/rules/index.md @@ -37,6 +37,14 @@ There is a config that enables the rules in this category: [`no-new-in-esnext`] | [es-x/no-set-prototype-union](./no-set-prototype-union.md) | disallow the `Set.prototype.union` method. | | | [es-x/no-trailing-dynamic-import-commas](./no-trailing-dynamic-import-commas.md) | disallow trailing commas in `import()`. | 🔧 | +## ES2025 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-durationformat](./no-intl-durationformat.md) | disallow the `Intl.DurationFormat` object. | | + ## ES2024 There are multiple configs that enable all rules in this category: [`no-new-in-es2024`], [`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`], and [`restrict-to-es2023`] @@ -406,6 +414,8 @@ Rules in this category are not included in any preset. | [es-x/no-nonstandard-intl-datetimeformat-prototype-properties](./no-nonstandard-intl-datetimeformat-prototype-properties.md) | disallow non-standard properties on Intl.DateTimeFormat instance. | | | [es-x/no-nonstandard-intl-displaynames-properties](./no-nonstandard-intl-displaynames-properties.md) | disallow non-standard static properties on `Intl.DisplayNames` class. | | | [es-x/no-nonstandard-intl-displaynames-prototype-properties](./no-nonstandard-intl-displaynames-prototype-properties.md) | disallow non-standard properties on Intl.DisplayNames instance. | | +| [es-x/no-nonstandard-intl-durationformat-properties](./no-nonstandard-intl-durationformat-properties.md) | disallow non-standard static properties on `Intl.DurationFormat` class. | | +| [es-x/no-nonstandard-intl-durationformat-prototype-properties](./no-nonstandard-intl-durationformat-prototype-properties.md) | disallow non-standard properties on Intl.DurationFormat instance. | | | [es-x/no-nonstandard-intl-listformat-properties](./no-nonstandard-intl-listformat-properties.md) | disallow non-standard static properties on `Intl.ListFormat` class. | | | [es-x/no-nonstandard-intl-listformat-prototype-properties](./no-nonstandard-intl-listformat-prototype-properties.md) | disallow non-standard properties on Intl.ListFormat instance. | | | [es-x/no-nonstandard-intl-locale-properties](./no-nonstandard-intl-locale-properties.md) | disallow non-standard static properties on `Intl.Locale` class. | | @@ -463,6 +473,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-es2024`]: ../configs/index.md#no-new-in-es2024 [`restrict-to-es2023`]: ../configs/index.md#restrict-to-es2023 [`restrict-to-es2023-intl-api`]: ../configs/index.md#restrict-to-es2023-intl-api diff --git a/docs/rules/no-intl-durationformat.md b/docs/rules/no-intl-durationformat.md new file mode 100644 index 00000000..d0691803 --- /dev/null +++ b/docs/rules/no-intl-durationformat.md @@ -0,0 +1,38 @@ +--- +title: "es-x/no-intl-durationformat" +description: "disallow the `Intl.DurationFormat` object" +--- + +# es-x/no-intl-durationformat +> disallow the `Intl.DurationFormat` object + +- ❗ ***This rule has not been released yet.*** +- ✅ The following configurations enable this rule: [no-new-in-esnext-intl-api] + +This rule reports ES2025 Intl API `Intl.DurationFormat` object as errors. + +## 💡 Examples + +⛔ Examples of **incorrect** code for this rule: + + + +```js +/*eslint es-x/no-intl-durationformat: error */ +const df = new Intl.DurationFormat("fr-FR", { style: "long" }); + +df.format({ + hours: 1, + minutes: 46, + seconds: 40, +}); +``` + + + +## 📚 References + +- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-intl-durationformat.js) +- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-intl-durationformat.js) + +[no-new-in-esnext-intl-api]: ../configs/index.md#no-new-in-esnext-intl-api diff --git a/docs/rules/no-nonstandard-intl-durationformat-properties.md b/docs/rules/no-nonstandard-intl-durationformat-properties.md new file mode 100644 index 00000000..6f049dae --- /dev/null +++ b/docs/rules/no-nonstandard-intl-durationformat-properties.md @@ -0,0 +1,50 @@ +--- +title: "es-x/no-nonstandard-intl-durationformat-properties" +description: "disallow non-standard static properties on `Intl.DurationFormat` class" +--- + +# es-x/no-nonstandard-intl-durationformat-properties +> disallow non-standard static properties on `Intl.DurationFormat` class + +- ❗ ***This rule has not been released yet.*** + +This rule reports non-standard static properties on `Intl.DurationFormat` class as errors. + +## 💡 Examples + +⛔ Examples of **incorrect** code for this rule: + + + +```js +/*eslint es-x/no-nonstandard-intl-durationformat-properties: error */ +Intl.DurationFormat.unknown(); +``` + + + +## 🔧 Options + +This rule has an option. + +```jsonc +{ + "rules": { + "es-x/no-nonstandard-intl-durationformat-properties": [ + "error", + { + "allow": [] + } + ] + } +} +``` + +### allow: string[] + +An array of non-standard property names to allow. + +## 📚 References + +- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-nonstandard-intl-durationformat-properties.js) +- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-nonstandard-intl-durationformat-properties.js) diff --git a/docs/rules/no-nonstandard-intl-durationformat-prototype-properties.md b/docs/rules/no-nonstandard-intl-durationformat-prototype-properties.md new file mode 100644 index 00000000..f9e8e994 --- /dev/null +++ b/docs/rules/no-nonstandard-intl-durationformat-prototype-properties.md @@ -0,0 +1,51 @@ +--- +title: "es-x/no-nonstandard-intl-durationformat-prototype-properties" +description: "disallow non-standard properties on Intl.DurationFormat instance" +--- + +# es-x/no-nonstandard-intl-durationformat-prototype-properties +> disallow non-standard properties on Intl.DurationFormat instance + +- ❗ ***This rule has not been released yet.*** + +This rule reports non-standard properties on Intl.DurationFormat instance as errors. + +## 💡 Examples + +⛔ Examples of **incorrect** code for this rule: + + + +```js +/*eslint es-x/no-nonstandard-intl-durationformat-prototype-properties: error */ +const df = new Intl.DurationFormat("fr-FR", { style: "long" }); +df.unknown(); +``` + + + +## 🔧 Options + +This rule has an option. + +```jsonc +{ + "rules": { + "es-x/no-nonstandard-intl-durationformat-prototype-properties": [ + "error", + { + "allow": [] + } + ] + } +} +``` + +### allow: string[] + +An array of non-standard property names to allow. + +## 📚 References + +- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js) +- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js) 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..91a1feab 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,5 @@ module.exports = { return require("../../index.js") }, }, - rules: {}, + rules: { "es-x/no-intl-durationformat": "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..71e35c13 100644 --- a/lib/configs/no-new-in-esnext-intl-api.js +++ b/lib/configs/no-new-in-esnext-intl-api.js @@ -4,4 +4,7 @@ */ "use strict" -module.exports = { plugins: ["es-x"], rules: {} } +module.exports = { + plugins: ["es-x"], + rules: { "es-x/no-intl-durationformat": "error" }, +} diff --git a/lib/index.js b/lib/index.js index f49eb1ae..aed64d3b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -213,6 +213,7 @@ module.exports = { "no-intl-datetimeformat-prototype-formatrange": require("./rules/no-intl-datetimeformat-prototype-formatrange"), "no-intl-datetimeformat-prototype-formattoparts": require("./rules/no-intl-datetimeformat-prototype-formattoparts"), "no-intl-displaynames": require("./rules/no-intl-displaynames"), + "no-intl-durationformat": require("./rules/no-intl-durationformat"), "no-intl-getcanonicallocales": require("./rules/no-intl-getcanonicallocales"), "no-intl-listformat": require("./rules/no-intl-listformat"), "no-intl-locale": require("./rules/no-intl-locale"), @@ -287,6 +288,8 @@ module.exports = { "no-nonstandard-intl-datetimeformat-prototype-properties": require("./rules/no-nonstandard-intl-datetimeformat-prototype-properties"), "no-nonstandard-intl-displaynames-properties": require("./rules/no-nonstandard-intl-displaynames-properties"), "no-nonstandard-intl-displaynames-prototype-properties": require("./rules/no-nonstandard-intl-displaynames-prototype-properties"), + "no-nonstandard-intl-durationformat-properties": require("./rules/no-nonstandard-intl-durationformat-properties"), + "no-nonstandard-intl-durationformat-prototype-properties": require("./rules/no-nonstandard-intl-durationformat-prototype-properties"), "no-nonstandard-intl-listformat-properties": require("./rules/no-nonstandard-intl-listformat-properties"), "no-nonstandard-intl-listformat-prototype-properties": require("./rules/no-nonstandard-intl-listformat-prototype-properties"), "no-nonstandard-intl-locale-properties": require("./rules/no-nonstandard-intl-locale-properties"), diff --git a/lib/rules/no-intl-durationformat.js b/lib/rules/no-intl-durationformat.js new file mode 100644 index 00000000..ffe8d888 --- /dev/null +++ b/lib/rules/no-intl-durationformat.js @@ -0,0 +1,27 @@ +"use strict" + +const { + defineStaticPropertiesHandler, +} = require("../util/define-static-properties-handler") + +module.exports = { + meta: { + docs: { + description: "disallow the `Intl.DurationFormat` object.", + category: "ES2025-Intl-API", + recommended: false, + url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-intl-durationformat.html", + }, + fixable: null, + messages: { + forbidden: "ES2025 Intl API '{{name}}' object is forbidden.", + }, + schema: [], + type: "problem", + }, + create(context) { + return defineStaticPropertiesHandler(context, { + Intl: ["DurationFormat"], + }) + }, +} diff --git a/lib/rules/no-nonstandard-intl-durationformat-properties.js b/lib/rules/no-nonstandard-intl-durationformat-properties.js new file mode 100644 index 00000000..ee991a5a --- /dev/null +++ b/lib/rules/no-nonstandard-intl-durationformat-properties.js @@ -0,0 +1,48 @@ +"use strict" + +const { + defineNonstandardStaticPropertiesHandler, +} = require("../util/define-nonstandard-static-properties-handler") +const { + intlDurationFormatProperties, +} = require("../util/well-known-properties") + +module.exports = { + meta: { + docs: { + description: + "disallow non-standard static properties on `Intl.DurationFormat` class", + category: "nonstandard", + recommended: false, + url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-nonstandard-intl-durationformat-properties.html", + }, + fixable: null, + messages: { + forbidden: "Non-standard '{{name}}' property is forbidden.", + }, + schema: [ + { + type: "object", + properties: { + allow: { + type: "array", + items: { type: "string" }, + uniqueItems: true, + }, + }, + additionalProperties: false, + }, + ], + type: "problem", + }, + create(context) { + /** @type {Set} */ + const allows = new Set([ + ...(context.options[0]?.allow || []), + ...intlDurationFormatProperties, + ]) + return defineNonstandardStaticPropertiesHandler(context, { + "Intl.DurationFormat": allows, + }) + }, +} diff --git a/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js b/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js new file mode 100644 index 00000000..7769da6a --- /dev/null +++ b/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js @@ -0,0 +1,48 @@ +"use strict" + +const { + defineNonstandardPrototypePropertiesHandler, +} = require("../util/define-nonstandard-prototype-properties-handler") +const { + intlDurationFormatPrototypeProperties, +} = require("../util/well-known-properties") + +module.exports = { + meta: { + docs: { + description: + "disallow non-standard properties on Intl.DurationFormat instance", + category: "nonstandard", + recommended: false, + url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-nonstandard-intl-durationformat-prototype-properties.html", + }, + fixable: null, + messages: { + forbidden: "Non-standard '{{name}}' property is forbidden.", + }, + schema: [ + { + type: "object", + properties: { + allow: { + type: "array", + items: { type: "string" }, + uniqueItems: true, + }, + }, + additionalProperties: false, + }, + ], + type: "problem", + }, + create(context) { + /** @type {Set} */ + const allows = new Set([ + ...(context.options[0]?.allow || []), + ...intlDurationFormatPrototypeProperties, + ]) + return defineNonstandardPrototypePropertiesHandler(context, { + "Intl.DurationFormat": allows, + }) + }, +} diff --git a/lib/util/type-checker/es-types.js b/lib/util/type-checker/es-types.js index 98cc05ee..bd1c293e 100644 --- a/lib/util/type-checker/es-types.js +++ b/lib/util/type-checker/es-types.js @@ -335,6 +335,11 @@ const WELLKNOWN_GLOBALS = { return: { type: "Intl.DisplayNames" }, prototypeType: "Intl.DisplayNames", }, + DurationFormat: { + type: "Function", + return: { type: "Intl.DurationFormat" }, + prototypeType: "Intl.DurationFormat", + }, Locale: { type: "Function", return: { type: "Intl.Locale" }, diff --git a/lib/util/type-checker/types.d.ts b/lib/util/type-checker/types.d.ts index 151ac039..ed921be1 100644 --- a/lib/util/type-checker/types.d.ts +++ b/lib/util/type-checker/types.d.ts @@ -11,6 +11,7 @@ export type TypeName = | "Intl.Segmenter" | "Intl.DisplayNames" | "Intl.Locale" + | "Intl.DurationFormat" | "Promise" | "RegExp" | "String" @@ -193,7 +194,7 @@ export type FinalizationRegistryPrototypeProperty = Exclude< keyof FinalizationRegistry, ExcludePrototypeProperty >; -export type IntlProperty = Exclude; +export type IntlProperty = Exclude | 'DurationFormat'; export type IteratorProperty = Exclude; export type IteratorPrototypeProperty = Exclude< keyof IteratorObject, diff --git a/lib/util/well-known-properties.js b/lib/util/well-known-properties.js index 806d1752..c4e0db40 100644 --- a/lib/util/well-known-properties.js +++ b/lib/util/well-known-properties.js @@ -949,6 +949,7 @@ const intlProperties = new Set([ "Collator", "DateTimeFormat", "DisplayNames", + "DurationFormat", "ListFormat", "Locale", "NumberFormat", @@ -1022,6 +1023,26 @@ const intlDisplayNamesPrototypeProperties = new Set([ "resolvedOptions", ]) +const intlDurationFormatProperties = new Set([ + ...objectPrototypeProperties, + ...functionPrototypeProperties, + + // https://tc39.es/ecma402/#sec-properties-of-intl-durationformat-constructor + "prototype", + "supportedLocalesOf", +]) + +const intlDurationFormatPrototypeProperties = new Set([ + ...objectPrototypeProperties, + + // https://tc39.es/ecma402/#sec-properties-of-intl-durationformat-prototype-object + "constructor", + // [ %Symbol.toStringTag% ] + "format", + "formatToParts", + "resolvedOptions", +]) + const intlListFormatProperties = new Set([ ...objectPrototypeProperties, ...functionPrototypeProperties, @@ -1213,6 +1234,8 @@ module.exports = { intlDateTimeFormatPrototypeProperties, intlDisplayNamesProperties, intlDisplayNamesPrototypeProperties, + intlDurationFormatProperties, + intlDurationFormatPrototypeProperties, intlListFormatProperties, intlListFormatPrototypeProperties, intlLocaleProperties, diff --git a/package.json b/package.json index a79e151d..9fb10380 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "opener": "^1.5.1", "rimraf": "^6.0.0", "semver": "^7.0.0", - "typescript": "^5.6.3", + "typescript": "^5.7.2", "vite-plugin-eslint4b": "^0.5.0", "vitepress": "^1.0.0", "vue-eslint-parser": "^9.0.0" diff --git a/scripts/new-rule.js b/scripts/new-rule.js index 86c0b7fc..9de241ba 100644 --- a/scripts/new-rule.js +++ b/scripts/new-rule.js @@ -7,14 +7,10 @@ const cp = require("child_process") const fs = require("fs") const path = require("path") -const { categories } = require("./rules") +const { LATEST_ES_YEAR } = require("./rules") const logger = console -const maxESVersion = Math.max( - ...Object.keys(categories).map((esVersion) => - /^ES\d+$/u.test(esVersion) ? Number(esVersion.slice(2)) : 0, - ), -) +const maxESVersion = LATEST_ES_YEAR + 1 // main ;((ruleId) => { diff --git a/scripts/rules.js b/scripts/rules.js index 090942da..978331f9 100644 --- a/scripts/rules.js +++ b/scripts/rules.js @@ -41,7 +41,7 @@ const LATEST_ES_YEAR = 2024 /** @type {Record} */ const categories = [ ...(function* () { - const max = new Date().getFullYear() + 1 + const max = new Date().getFullYear() + 2 for (let year = max; year >= 2015; year--) { yield year } @@ -195,4 +195,4 @@ const rules = [] } })(libRoot) -module.exports = { categories, rules } +module.exports = { categories, rules, LATEST_ES_YEAR } diff --git a/tests/fixtures/tsconfig.json b/tests/fixtures/tsconfig.json index b843eb5a..2e6e7a54 100644 --- a/tests/fixtures/tsconfig.json +++ b/tests/fixtures/tsconfig.json @@ -3,5 +3,5 @@ "strict": true, "lib": ["ESNext"] }, - "include": ["test.ts"] + "include": ["test.ts", "types.d.ts"] } diff --git a/tests/fixtures/types.d.ts b/tests/fixtures/types.d.ts new file mode 100644 index 00000000..b453fd87 --- /dev/null +++ b/tests/fixtures/types.d.ts @@ -0,0 +1,14 @@ +/* Since typescript doesn't define the types yet, we'll work around the issue by defining the types ourselves. */ +declare namespace Intl { + interface DurationFormat { + format(duration: any): any; + formatToParts(duration: any): any; + resolvedOptions(): any; + } + + const DurationFormat: { + prototype: DurationFormat; + new (...args:any[]): DurationFormat; + supportedLocalesOf(...args:any[]): any; + }; +} diff --git a/tests/lib/rules/no-intl-durationformat.js b/tests/lib/rules/no-intl-durationformat.js new file mode 100644 index 00000000..5b845ced --- /dev/null +++ b/tests/lib/rules/no-intl-durationformat.js @@ -0,0 +1,21 @@ +"use strict" + +const RuleTester = require("../../tester") +const rule = require("../../../lib/rules/no-intl-durationformat") + +new RuleTester().run("no-intl-durationformat", rule, { + valid: [ + "Intl", + "Intl.DateTimeFormat", + "Intl.NumberFormat", + "let Intl = 0; Intl.DurationFormat", + ], + invalid: [ + { + code: "Intl.DurationFormat", + errors: [ + "ES2025 Intl API 'Intl.DurationFormat' object is forbidden.", + ], + }, + ], +}) diff --git a/tests/lib/rules/no-nonstandard-intl-durationformat-properties.js b/tests/lib/rules/no-nonstandard-intl-durationformat-properties.js new file mode 100644 index 00000000..099930a1 --- /dev/null +++ b/tests/lib/rules/no-nonstandard-intl-durationformat-properties.js @@ -0,0 +1,39 @@ +"use strict" + +const RuleTester = require("../../tester") +const rule = require("../../../lib/rules/no-nonstandard-intl-durationformat-properties.js") +const { + intlDurationFormatProperties, +} = require("../../../lib/util/well-known-properties") + +new RuleTester().run("no-nonstandard-intl-durationformat-properties", rule, { + valid: [ + ...[...intlDurationFormatProperties].map( + (p) => `Intl.DurationFormat.${p}`, + ), + { + code: "Intl.DurationFormat.unknown()", + options: [{ allow: ["unknown"] }], + }, + ], + invalid: [ + { + code: "Intl.DurationFormat.unknown()", + errors: [ + "Non-standard 'Intl.DurationFormat.unknown' property is forbidden.", + ], + }, + { + code: "Intl.DurationFormat.foo", + errors: [ + "Non-standard 'Intl.DurationFormat.foo' property is forbidden.", + ], + }, + { + code: "Intl.DurationFormat.bar", + errors: [ + "Non-standard 'Intl.DurationFormat.bar' property is forbidden.", + ], + }, + ], +}) diff --git a/tests/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js b/tests/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js new file mode 100644 index 00000000..cc804359 --- /dev/null +++ b/tests/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js @@ -0,0 +1,143 @@ +"use strict" + +const path = require("path") +const RuleTester = require("../../tester") +const rule = require("../../../lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js") +const { + intlDurationFormatPrototypeProperties, +} = require("../../../lib/util/well-known-properties") +const ruleId = "no-nonstandard-intl-durationformat-prototype-properties" + +new RuleTester().run(ruleId, rule, { + valid: [ + "foo", + "foo.toString", + "foo.foo", + ...[...intlDurationFormatPrototypeProperties].map( + (p) => `new Intl.DurationFormat().${p}`, + ), + { + code: "new Intl.DurationFormat().unknown()", + options: [{ allow: ["unknown"] }], + }, + ], + invalid: [ + { + code: "new Intl.DurationFormat().unknown()", + errors: [ + "Non-standard 'Intl.DurationFormat.prototype.unknown' property is forbidden.", + ], + }, + { + code: "new Intl.DurationFormat().foo", + errors: [ + "Non-standard 'Intl.DurationFormat.prototype.foo' property is forbidden.", + ], + }, + { + code: "new Intl.DurationFormat().bar", + errors: [ + "Non-standard 'Intl.DurationFormat.prototype.bar' property is forbidden.", + ], + }, + { + code: "new Intl.DurationFormat()[0]", + errors: [ + "Non-standard 'Intl.DurationFormat.prototype.0' property is forbidden.", + ], + }, + { + code: "new Intl.DurationFormat()['0']", + errors: [ + "Non-standard 'Intl.DurationFormat.prototype.0' property is forbidden.", + ], + }, + { + code: "new Intl.DurationFormat()['01']", + errors: [ + "Non-standard 'Intl.DurationFormat.prototype.01' 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: "foo" }, + { filename, code: "foo.toString" }, + { filename, code: "foo.foo" }, + { filename, code: "let foo = {}; foo.foo" }, + ...[...intlDurationFormatPrototypeProperties].map((p) => ({ + filename, + code: `new Intl.DurationFormat().${p}`, + })), + ], + invalid: [ + { + filename, + code: "new Intl.DurationFormat().foo", + errors: [ + "Non-standard 'Intl.DurationFormat.prototype.foo' property is forbidden.", + ], + }, + { + filename, + code: "new Intl.DurationFormat().bar", + errors: [ + "Non-standard 'Intl.DurationFormat.prototype.bar' property is forbidden.", + ], + }, + { + filename, + code: "new Intl.DurationFormat()[0]", + errors: [ + "Non-standard 'Intl.DurationFormat.prototype.0' property is forbidden.", + ], + }, + { + filename, + code: "new Intl.DurationFormat()['0']", + errors: [ + "Non-standard 'Intl.DurationFormat.prototype.0' property is forbidden.", + ], + }, + { + filename, + code: "new Intl.DurationFormat()['01']", + errors: [ + "Non-standard 'Intl.DurationFormat.prototype.01' property is forbidden.", + ], + }, + { + filename, + code: "let foo = new Intl.DurationFormat(); foo.foo", + errors: [ + "Non-standard 'Intl.DurationFormat.prototype.foo' property is forbidden.", + ], + }, + { + filename, + code: "function f(a: T) { a.baz }", + errors: [ + "Non-standard 'Intl.DurationFormat.prototype.baz' property is forbidden.", + ], + }, + ], +})