Files

Return to Package Diff Home.
Brought to you by Intrinsic.

Package Diff: eslint @ 5.12.0 .. 5.16.0

CHANGELOG.md

@@ -1,3 +1,136 @@
+v5.16.0 - March 29, 2019
+
+* [`dfef227`](https://github.com/eslint/eslint/commit/dfef227091955a2f8f3fa8c76ad79de8a77e7955) Build: gensite passes rulesMeta to formatter rendering (#11567) (Kevin Partington)
+* [`c06d38c`](https://github.com/eslint/eslint/commit/c06d38c81bd9203c904587396a65d3c8cc7f2944) Fix: Allow HTML formatter to handle no meta data (#11566) (Ilya Volodin)
+* [`87a5c03`](https://github.com/eslint/eslint/commit/87a5c034977cf4538ff3539d2f8776a987c5942a) Docs: `func-style`: clarify when `allowArrowFunctions` is used (#11548) (Oliver Joseph Ash)
+* [`bc3e427`](https://github.com/eslint/eslint/commit/bc3e427ee8875c53eac6b6762884b50074f1adfc) Update: pass rule meta to formatters RFC 10 (#11551) (Chris Meyer)
+* [`b452f27`](https://github.com/eslint/eslint/commit/b452f270bc0b523d88d5d827c95be3096f82e99d) Chore: Update README to pull in reviewer data (#11506) (Nicholas C. Zakas)
+* [`afe3d25`](https://github.com/eslint/eslint/commit/afe3d25f8afb88caee43f7202d0eb96f33a92a6b) Upgrade: Bump js-yaml dependency to fix Denial of Service vulnerability (#11550) (Vernon de Goede)
+* [`4fe7eb7`](https://github.com/eslint/eslint/commit/4fe7eb7cecdc2395cf1eeaa20921bda8460b00c2) Chore: use nyc instead of istanbul (#11532) (Toru Nagashima)
+* [`f16af43`](https://github.com/eslint/eslint/commit/f16af439694aab473c647d8fae47c402bd489447) Chore: fix formatters/table test (#11534) (Toru Nagashima)
+* [`78358a8`](https://github.com/eslint/eslint/commit/78358a8f66e95c4fcc921f2497e8a5ec5f1537ec) Docs: fix duplicate punctuation in CLI docs (#11528) (Teddy Katz)
+
+v5.15.3 - March 18, 2019
+
+* [`71adc66`](https://github.com/eslint/eslint/commit/71adc665b9649b173adc76f80723b8de20664ae1) Fix: avoid moving comments in implicit-arrow-linebreak (fixes #11521) (#11522) (Teddy Katz)
+* [`1f715a2`](https://github.com/eslint/eslint/commit/1f715a20c145d8ccc38f3310afccd838495d09d4) Chore: make test-case-property-ordering reasonable (#11511) (Toru Nagashima)
+
+v5.15.2 - March 15, 2019
+
+* [`29dbca7`](https://github.com/eslint/eslint/commit/29dbca73d762a809adb2f457b527e144426d54a7) Fix: implicit-arrow-linebreak adds extra characters (fixes #11268) (#11407) (Mark de Dios)
+* [`5d2083f`](https://github.com/eslint/eslint/commit/5d2083fa3e14c024197f6c386ff72237a145e258) Upgrade: eslint-scope@4.0.3 (#11513) (Teddy Katz)
+* [`a5dae7c`](https://github.com/eslint/eslint/commit/a5dae7c3d30231c2f5f075d98c2c8825899bab16) Fix: Empty glob pattern incorrectly expands to "/**" (#11476) (Ben Chauvette)
+* [`448e8da`](https://github.com/eslint/eslint/commit/448e8da94d09b397e98ffcb6f22b55a578ef79c1) Chore: improve crash reporting (fixes #11304) (#11463) (Alex Zherdev)
+* [`0f56dc6`](https://github.com/eslint/eslint/commit/0f56dc6d9eadad05dc3d5c9d1d9ddef94e10c5d3) Chore: make config validator params more consistent (#11435) (薛定谔的猫)
+* [`d6c1122`](https://github.com/eslint/eslint/commit/d6c112289f0f16ade070865c8786831b7940ca79) Docs: Add working groups to maintainer guide (#11400) (Nicholas C. Zakas)
+* [`5fdb4d3`](https://github.com/eslint/eslint/commit/5fdb4d3fb01b9d8a4c2dff71ed9cddb2f8feefb0) Build: compile deps to ES5 when generating browser file (fixes #11504) (#11505) (Teddy Katz)
+* [`06fa165`](https://github.com/eslint/eslint/commit/06fa1655c3da8394ed9144d727115fc434b0416f) Build: update CI testing configuration (#11500) (Reece Dunham)
+* [`956e883`](https://github.com/eslint/eslint/commit/956e883c21fd9f393bf6718d032a4e2e53b33f22) Docs: Fix example in no-restricted-modules docs (#11454) (Paul O’Shannessy)
+* [`2c7431d`](https://github.com/eslint/eslint/commit/2c7431d6b32063f74e3837ee727f26af215eada7) Docs: fix json schema example dead link (#11498) (kazuya kawaguchi)
+* [`e7266c2`](https://github.com/eslint/eslint/commit/e7266c2478aff5d66e7859313feb49e3a129f85e) Docs: Fix invalid JSON in "Specifying Parser Options" (#11492) (Mihira Jayasekera)
+* [`6693161`](https://github.com/eslint/eslint/commit/6693161978a83e0730d5ea0fecdb627c5a2acdfd) Sponsors: Sync README with website (ESLint Jenkins)
+* [`62fee4a`](https://github.com/eslint/eslint/commit/62fee4a976897d158c8c137339728cd280333286) Chore: eslint-config-eslint enable comma-dangle functions: "never" (#11434) (薛定谔的猫)
+* [`34a5382`](https://github.com/eslint/eslint/commit/34a53829e7a63ff2f6b371d77ce283bbdd373b91) Build: copy bundled espree to website directory (#11478) (Pig Fang)
+* [`f078f9a`](https://github.com/eslint/eslint/commit/f078f9a9e094ec00c61a6ef1c9550d017631e69a) Chore: use "file:" dependencies for internal rules/config (#11465) (Teddy Katz)
+* [`0756128`](https://github.com/eslint/eslint/commit/075612871f85aa04cef8137bd32247e128ad600b) Docs: Add `visualstudio` to formatter list (#11480) (Patrick Eriksson)
+* [`44de9d7`](https://github.com/eslint/eslint/commit/44de9d7e1aa2fcae475a97b8f597b7d8094566b2) Docs: Fix typo in func-name-matching rule docs (#11484) (Iulian Onofrei)
+
+v5.15.1 - March 4, 2019
+
+* [`fe1a892`](https://github.com/eslint/eslint/commit/fe1a892f85b09c3d2fea05bef011530a678a6af5) Build: bundle espree (fixes eslint/eslint.github.io#546) (#11467) (薛定谔的猫)
+* [`458053b`](https://github.com/eslint/eslint/commit/458053b0b541f857bf233dacbde5ba80681820f8) Fix: avoid creating invalid regex in no-warning-comments (fixes #11471) (#11472) (Teddy Katz)
+
+v5.15.0 - March 1, 2019
+
+* [`4088c6c`](https://github.com/eslint/eslint/commit/4088c6c9d4578cd581ce8ff4385d90b58a75b755) Build: Remove path.resolve in webpack build (#11462) (Kevin Partington)
+* [`ec59ec0`](https://github.com/eslint/eslint/commit/ec59ec09c8d001b8c04f9edc09994e2b0d0af0f9) New: add rule "prefer-named-capture-group" (fixes #11381) (#11392) (Pig Fang)
+* [`a44f750`](https://github.com/eslint/eslint/commit/a44f75073306e5ea4e6722654009a99884fbca4f) Upgrade: eslint-scope@4.0.2 (#11461) (Teddy Katz)
+* [`d3ce611`](https://github.com/eslint/eslint/commit/d3ce611e1c705440ccbcae357f2194134d026541) Sponsors: Sync README with website (ESLint Jenkins)
+* [`ee88475`](https://github.com/eslint/eslint/commit/ee884754e4111e11994ff0df3f0c29e43e1dc3f2) Chore: add utils for rule tests (#11453) (薛定谔的猫)
+* [`d4824e4`](https://github.com/eslint/eslint/commit/d4824e46d7a6ca1618454d3c6198403382108123) Sponsors: Sync README with website (ESLint Jenkins)
+* [`6489518`](https://github.com/eslint/eslint/commit/64895185bde5233223648bcaf46f8deb72c9fb55) Fix: no-extra-parens crash when code is "((let))" (#11444) (Teddy Katz)
+* [`9d20de2`](https://github.com/eslint/eslint/commit/9d20de2b0ac756bd62888119b8e08c7441d8a5aa) Sponsors: Sync README with website (ESLint Jenkins)
+* [`3f14de4`](https://github.com/eslint/eslint/commit/3f14de458ba120e9c013f5fc7c6fe3e9b40c1460) Sponsors: Sync README with website (ESLint Jenkins)
+* [`3d6c770`](https://github.com/eslint/eslint/commit/3d6c7709d47e047b25d91ca1a77d6dab92313061) Sponsors: Sync README with website (ESLint Jenkins)
+* [`de5cbc5`](https://github.com/eslint/eslint/commit/de5cbc526b30405e742b35d85d04361529d49ed4) Update: remove invalid defaults from core rules (fixes #11415) (#11427) (Teddy Katz)
+* [`eb0650b`](https://github.com/eslint/eslint/commit/eb0650ba20cf9f9ad78dbaccfeb7e0e7ab56e31d) Build: fix linting errors on master (#11428) (Teddy Katz)
+* [`5018378`](https://github.com/eslint/eslint/commit/5018378131fd5190bbccca902c0cf4276ee1581a) Chore: enable require-unicode-regexp on ESLint codebase (#11422) (Teddy Katz)
+* [`f6ba633`](https://github.com/eslint/eslint/commit/f6ba633f56eca6be20fc4b0d9496a78b9498d578) Chore: lint all files in the repo at the same time (#11425) (Teddy Katz)
+* [`8f3d717`](https://github.com/eslint/eslint/commit/8f3d71754932669332ad7623bcc4c1aef3897125) Docs: Add non-attending TSC member info (#11411) (Nicholas C. Zakas)
+* [`ce0777d`](https://github.com/eslint/eslint/commit/ce0777da5bc167fe0c529158fd8216d3eaf11565) Docs: use more common spelling (#11417) (薛定谔的猫)
+* [`b9aabe3`](https://github.com/eslint/eslint/commit/b9aabe34311f6189b87c9d8a1aa40f3513fed773) Chore: run fuzzer along with unit tests (#11404) (Teddy Katz)
+* [`db0c5e2`](https://github.com/eslint/eslint/commit/db0c5e2a7f894b7cda71007b0ba43d7814b3fb2e) Build: switch from browserify to webpack (fixes #11366) (#11398) (Pig Fang)
+
+v5.14.1 - February 18, 2019
+
+* [`1d6e639`](https://github.com/eslint/eslint/commit/1d6e63930073e79e52890f552cc6e9a0646b7fb4) Fix: sort-keys throws Error at SpreadElement (fixes #11402) (#11403) (Krist Wongsuphasawat)
+
+v5.14.0 - February 15, 2019
+
+* [`85a04b3`](https://github.com/eslint/eslint/commit/85a04b319e6dfde1458174cd1d8c9e7d33da0871) Fix: adds conditional for separateRequires in one-var (fixes #10179) (#10980) (Scott Stern)
+* [`0c02932`](https://github.com/eslint/eslint/commit/0c02932f1b2e2a85809e84617efa1b8836c19cfb) Upgrade: espree@5.0.1 (#11401) (Ilya Volodin)
+* [`104ae88`](https://github.com/eslint/eslint/commit/104ae881d0b21e9c64e006b2a2c21535cef0ad28) Docs: Update governance doc with reviewers status (#11399) (Nicholas C. Zakas)
+* [`ab8ac6a`](https://github.com/eslint/eslint/commit/ab8ac6adaaf7a88e160899e7f438a4cfd655eb6e) Fix: Support boundary spread elements in sort-keys (#11158) (Jakub Rożek)
+* [`a23d197`](https://github.com/eslint/eslint/commit/a23d1975d48841eafdead1a1357e2af842f688bc) New: add allowSingleLineBlocks opt. to padded-blocks rule (fixes #7145) (#11243) (richie3366)
+* [`e25e7aa`](https://github.com/eslint/eslint/commit/e25e7aa3ea1e8c9b3cd3242acda6d4a5572c2c6a) Fix: comma-spacing ignore comma before closing paren (fixes #11295) (#11374) (Pig Fang)
+* [`a1f7c44`](https://github.com/eslint/eslint/commit/a1f7c44ea9efbd9393889c1cc91b74260e0a8e02) Docs: fix space-before-blocks correct code for "classes": "never" (#11391) (PoziWorld)
+* [`14f58a2`](https://github.com/eslint/eslint/commit/14f58a2bec4d6aade0de22771c378b86b1e51959) Docs: fix grammar in object-curly-spacing docs (#11389) (PoziWorld)
+* [`d3e9a27`](https://github.com/eslint/eslint/commit/d3e9a27bbba30008a610df59e82b7192f0ecc3a3) Docs: fix grammar in “those who says” (#11390) (PoziWorld)
+* [`ea8e804`](https://github.com/eslint/eslint/commit/ea8e8045ba0e6c1e1015104346af962f3e16fd81) Docs: Add note about support for object spread (fixes #11136) (#11395) (Steven Thomas)
+* [`95aa3fd`](https://github.com/eslint/eslint/commit/95aa3fdb392d265e6c3d813d54076458e88e7ad8) Docs: Update README team and sponsors (ESLint Jenkins)
+* [`51c4972`](https://github.com/eslint/eslint/commit/51c497298a15ad296a2b1f8fc397df687976b836) Update: Behavior of --init (fixes #11105) (#11332) (Nicholas C. Zakas)
+* [`ad7a380`](https://github.com/eslint/eslint/commit/ad7a38097c32a91e5a831ef1bc8933601532576c) Docs: Update README team and sponsors (ESLint Jenkins)
+* [`550de1e`](https://github.com/eslint/eslint/commit/550de1e611a1e9af873bcb18d74cf2056e8d2e1b) Update: use `default` keyword in JSON schema (fixes #9929) (#11288) (Pig Fang)
+* [`983c520`](https://github.com/eslint/eslint/commit/983c5201210d7a4ffab0b3d05ab9919c0754e5ca) Update: Use 'readonly' and 'writable' for globals (fixes #11359) (#11384) (Nicholas C. Zakas)
+* [`f1d3a7e`](https://github.com/eslint/eslint/commit/f1d3a7ee7c82365989e219b1dae379f08f6dd526) Upgrade: some deps (fixes #11372) (#11373) (薛定谔的猫)
+* [`3e0c417`](https://github.com/eslint/eslint/commit/3e0c4176eff085498b813f8ba1732d7ed6ee44f8) Docs: Fix grammar in “there’s nothing prevent you” (#11385) (PoziWorld)
+* [`de988bc`](https://github.com/eslint/eslint/commit/de988bc909b491366ad0cd9bc83f4d6de42d041a) Docs: Fix grammar: Spacing improve -> Spacing improves (#11386) (PoziWorld)
+* [`1309dfd`](https://github.com/eslint/eslint/commit/1309dfdebb5595460b79dcac20df6a1f109e7566) Revert "Build: fix test failure on Node 11 (#11100)" (#11375) (薛定谔的猫)
+* [`1e56897`](https://github.com/eslint/eslint/commit/1e56897db3e254e0aef6d2fe3274157fc379c79e) Docs: “the function actually use”: use -> uses (#11380) (PoziWorld)
+* [`5a71bc9`](https://github.com/eslint/eslint/commit/5a71bc95a7e961b1b1b77022645e0bd9cdd08dc0) Docs: Update README team and sponsors (ESLint Jenkins)
+* [`82a58ce`](https://github.com/eslint/eslint/commit/82a58ce26b282fd80335b3ac4fc88f21266c3ba1) Docs: Update README team and sponsors (ESLint Jenkins)
+* [`546d355`](https://github.com/eslint/eslint/commit/546d355ace65631e27de859baea3ffcc50e0ad2c) Docs: Update README with latest sponsors/team data (#11378) (Nicholas C. Zakas)
+* [`c0df9fe`](https://github.com/eslint/eslint/commit/c0df9febb7c7e045ababc10b88dbcbb3f28c724c) Docs: `...` is not an operator (#11232) (Felix Kling)
+* [`7ecfdef`](https://github.com/eslint/eslint/commit/7ecfdefaeadb772f8b96ffe37c4a2c97fde0da16) Docs: update typescript parser (refs #11368) (#11369) (薛定谔的猫)
+* [`3c90dd7`](https://github.com/eslint/eslint/commit/3c90dd7e25cf97833deddb11cfbc107a5663ac08) Update: remove prefer-spread autofix (fixes #11330) (#11365) (薛定谔的猫)
+* [`5eb3121`](https://github.com/eslint/eslint/commit/5eb3121b82c1837da0c3021b7d9384bb30832e36) Update: add fixer for `prefer-destructuring` (fixes #11151) (#11301) (golopot)
+* [`173eb38`](https://github.com/eslint/eslint/commit/173eb38cdb3e4673cba947521f27158828186d77) Docs: Clarify ecmaVersion doesn't imply globals (refs #9812) (#11364) (Keith Maxwell)
+* [`84ce72f`](https://github.com/eslint/eslint/commit/84ce72fdeba082b7b132e4ac6b714fb1a93831b7) Fix: Remove extraneous linefeeds in `one-var` fixer (fixes #10741) (#10955) (st-sloth)
+* [`389362a`](https://github.com/eslint/eslint/commit/389362a06ac6601512b872d3e843c7371f2a1bcc) Docs: clarify motivation for no-prototype-builtins (#11356) (Teddy Katz)
+* [`533d240`](https://github.com/eslint/eslint/commit/533d240b0811f663494cb213b06cc9e51e1ff2d0) Update: no-shadow-restricted-names lets unassigned vars shadow undefined (#11341) (Teddy Katz)
+* [`d0e823a`](https://github.com/eslint/eslint/commit/d0e823aef196a6564c87a78b72c1ef980ce67af9) Update: Make --init run js config files through linter (fixes #9947) (#11337) (Brian Kurek)
+* [`92fc2f4`](https://github.com/eslint/eslint/commit/92fc2f4f3faf8aeaae8a8e71db0de405404fb6c3) Fix: CircularJSON dependency warning (fixes #11052) (#11314) (Terry)
+* [`4dd19a3`](https://github.com/eslint/eslint/commit/4dd19a3c4c037adc860a65e96f2ba3eeccace1de) Docs: mention 'prefer-spread' in docs of 'no-useless-call' (#11348) (Klaus Meinhardt)
+* [`4fd83d5`](https://github.com/eslint/eslint/commit/4fd83d5ec47a6a7b81cd8801c3bd63d27ea1c7c4) Docs: fix a misleading example in one-var (#11350) (薛定谔的猫)
+* [`9441ce7`](https://github.com/eslint/eslint/commit/9441ce77b7228f2c4562e158a10905afe11f31f2) Chore: update incorrect tests to fix build failing (#11354) (薛定谔的猫)
+
+v5.13.0 - February 1, 2019
+
+* [`91c8884`](https://github.com/eslint/eslint/commit/91c8884971f5e57f5f7490d8daf92c4a9a489836) Chore: use local function to append "s" instead of a package (#11293) (Timo Tijhof)
+* [`b5143bf`](https://github.com/eslint/eslint/commit/b5143bfc09e53d8da8f63421ade093b7593f4f51) Update: for-direction detection false positives/negatives (#11254) (Ruben Bridgewater)
+* [`9005e63`](https://github.com/eslint/eslint/commit/9005e632d13476880c55f7e3c8a6e450762a5171) Chore: increase camelcase test coverage (#11299) (Redmond Tran)
+* [`5b14ad1`](https://github.com/eslint/eslint/commit/5b14ad1003c7df9a37621dea55c6d6d0484adc05) Fix: false positive in no-constant-condition (fixes #11306) (#11308) (Pig Fang)
+* [`6567c4f`](https://github.com/eslint/eslint/commit/6567c4f6665df85c3347388b29d8193cc8208d63) Fix: only remove arrow before body in object-shorthand (fixes #11305) (#11307) (Pig Fang)
+* [`fa2f370`](https://github.com/eslint/eslint/commit/fa2f370affa4814dbdda278f9859d0172d4b7aa2) Docs: update rule configuration values in examples (#11323) (Kai Cataldo)
+* [`0a3c3ff`](https://github.com/eslint/eslint/commit/0a3c3ff1d91e8f39943efc4a7d2bf6927d68d37e) New: Allow globals to be disabled/configured with strings (fixes #9940) (#11338) (Teddy Katz)
+* [`dccee63`](https://github.com/eslint/eslint/commit/dccee63cf41234180c71bf0fe01b165c9078fc69) Chore: avoid hard-coding the list of core rules in eslint:recommended (#11336) (Teddy Katz)
+* [`c1fd6f5`](https://github.com/eslint/eslint/commit/c1fd6f54d92efe615bcae529006221e122dbe9e6) Chore: remove undocumented `Linter#rules` property (refs #9161) (#11335) (Teddy Katz)
+* [`36e3356`](https://github.com/eslint/eslint/commit/36e335681d61cbe3c83b653b7cc5f95730f1d86e) Chore: remove dead code for loading rules (#11334) (Teddy Katz)
+* [`c464e27`](https://github.com/eslint/eslint/commit/c464e2744ec76e7e9c6c5af0f6162c92187f1ece) Docs: Rename `result` -> `foo` (#11210) (Alexis Tyler)
+
+v5.12.1 - January 18, 2019
+
+* [`eb5c401`](https://github.com/eslint/eslint/commit/eb5c4014f16be1c2003ed46ce9560d0d8a567d0f) Chore: use meta.messages in some rules (2/4) (refs #9870) (#10773) (薛定谔的猫)
+* [`aa56247`](https://github.com/eslint/eslint/commit/aa56247746a0095996a41dd03bdbbf659f0f93b6) Fix: avoid loading core rules dynamically from FS in Linter (#11278) (Peter Metz)
+* [`04450bb`](https://github.com/eslint/eslint/commit/04450bb7ed20f2412102538b238119d9764b4dc9) Docs: clarify process for adding committers (#11272) (Kai Cataldo)
+* [`3ffcf26`](https://github.com/eslint/eslint/commit/3ffcf26c1c83efe7d7cf2d87f1063695ae653709) Docs: add @g-plane as committer (#11277) (Kai Cataldo)
+* [`c403445`](https://github.com/eslint/eslint/commit/c40344566eff2e77a6ae2b2d2dbdbd4ad3e76b67) Fix: warn constant on RHS of || in no-constant-condition (fixes #11181) (#11253) (Merlin Mason)
+* [`9194f45`](https://github.com/eslint/eslint/commit/9194f45ac7d521119a53773bf02b81670bad526e) Fix: Manage severity of 1 with TAP reporter (fixes #11110) (#11221) (Gabriel Cousin)
+* [`000f495`](https://github.com/eslint/eslint/commit/000f4952ae6a4311fbbc3ed36c481235fcb0b64b) Docs: fix example for sort-imports ignoreDeclarationSort (#11242) (Remco Haszing)
+* [`7c0bf2c`](https://github.com/eslint/eslint/commit/7c0bf2ca92d83125a1fa000c9c4250bae6b4fc21) Docs: Add `npx` usage to Getting Started guide (#11249) (eyal0803)
+* [`da9174e`](https://github.com/eslint/eslint/commit/da9174e0798c1d785ddabb3ae405860fc5b89311) Docs: fixes typo peerDepencies (#11252) (Christian Kühl)
+* [`9c31625`](https://github.com/eslint/eslint/commit/9c31625f19176664ef76dcf088ce50703c41c324) Docs: Improve custom formatter docs (#11258) (Nicholas C. Zakas)
+
v5.12.0 - January 4, 2019
* [`0d91e7d`](https://github.com/eslint/eslint/commit/0d91e7d28e5eba79a6032165cdef5d4549d26462) Update: Add sort-imports ignoreDeclarationSort (fixes #11019) (#11040) (Remco Haszing)

conf/eslint-all.js

@@ -9,16 +9,14 @@
// Requirements
//------------------------------------------------------------------------------
-const load = require("../lib/load-rules"),
- Rules = require("../lib/rules");
-const rules = new Rules();
+const builtInRules = require("../lib/built-in-rules-index");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
-const enabledRules = Object.keys(load()).reduce((result, ruleId) => {
- if (!rules.get(ruleId).meta.deprecated) {
+const enabledRules = Object.keys(builtInRules).reduce((result, ruleId) => {
+ if (!builtInRules[ruleId].meta.deprecated) {
result[ruleId] = "error";
}
return result;

conf/eslint-recommended.js

@@ -6,274 +6,10 @@
"use strict";
-/* eslint sort-keys: ["error", "asc"] */
+const builtInRules = require("../lib/built-in-rules-index");
module.exports = {
- rules: {
- "accessor-pairs": "off",
- "array-bracket-newline": "off",
- "array-bracket-spacing": "off",
- "array-callback-return": "off",
- "array-element-newline": "off",
- "arrow-body-style": "off",
- "arrow-parens": "off",
- "arrow-spacing": "off",
- "block-scoped-var": "off",
- "block-spacing": "off",
- "brace-style": "off",
- "callback-return": "off",
- camelcase: "off",
- "capitalized-comments": "off",
- "class-methods-use-this": "off",
- "comma-dangle": "off",
- "comma-spacing": "off",
- "comma-style": "off",
- complexity: "off",
- "computed-property-spacing": "off",
- "consistent-return": "off",
- "consistent-this": "off",
- "constructor-super": "error",
- curly: "off",
- "default-case": "off",
- "dot-location": "off",
- "dot-notation": "off",
- "eol-last": "off",
- eqeqeq: "off",
- "for-direction": "error",
- "func-call-spacing": "off",
- "func-name-matching": "off",
- "func-names": "off",
- "func-style": "off",
- "function-paren-newline": "off",
- "generator-star-spacing": "off",
- "getter-return": "error",
- "global-require": "off",
- "guard-for-in": "off",
- "handle-callback-err": "off",
- "id-blacklist": "off",
- "id-length": "off",
- "id-match": "off",
- "implicit-arrow-linebreak": "off",
- indent: "off",
- "indent-legacy": "off",
- "init-declarations": "off",
- "jsx-quotes": "off",
- "key-spacing": "off",
- "keyword-spacing": "off",
- "line-comment-position": "off",
- "linebreak-style": "off",
- "lines-around-comment": "off",
- "lines-around-directive": "off",
- "lines-between-class-members": "off",
- "max-classes-per-file": "off",
- "max-depth": "off",
- "max-len": "off",
- "max-lines": "off",
- "max-lines-per-function": "off",
- "max-nested-callbacks": "off",
- "max-params": "off",
- "max-statements": "off",
- "max-statements-per-line": "off",
- "multiline-comment-style": "off",
- "multiline-ternary": "off",
- "new-cap": "off",
- "new-parens": "off",
- "newline-after-var": "off",
- "newline-before-return": "off",
- "newline-per-chained-call": "off",
- "no-alert": "off",
- "no-array-constructor": "off",
- "no-async-promise-executor": "off",
- "no-await-in-loop": "off",
- "no-bitwise": "off",
- "no-buffer-constructor": "off",
- "no-caller": "off",
- "no-case-declarations": "error",
- "no-catch-shadow": "off",
- "no-class-assign": "error",
- "no-compare-neg-zero": "error",
- "no-cond-assign": "error",
- "no-confusing-arrow": "off",
- "no-console": "error",
- "no-const-assign": "error",
- "no-constant-condition": "error",
- "no-continue": "off",
- "no-control-regex": "error",
- "no-debugger": "error",
- "no-delete-var": "error",
- "no-div-regex": "off",
- "no-dupe-args": "error",
- "no-dupe-class-members": "error",
- "no-dupe-keys": "error",
- "no-duplicate-case": "error",
- "no-duplicate-imports": "off",
- "no-else-return": "off",
- "no-empty": "error",
- "no-empty-character-class": "error",
- "no-empty-function": "off",
- "no-empty-pattern": "error",
- "no-eq-null": "off",
- "no-eval": "off",
- "no-ex-assign": "error",
- "no-extend-native": "off",
- "no-extra-bind": "off",
- "no-extra-boolean-cast": "error",
- "no-extra-label": "off",
- "no-extra-parens": "off",
- "no-extra-semi": "error",
- "no-fallthrough": "error",
- "no-floating-decimal": "off",
- "no-func-assign": "error",
- "no-global-assign": "error",
- "no-implicit-coercion": "off",
- "no-implicit-globals": "off",
- "no-implied-eval": "off",
- "no-inline-comments": "off",
- "no-inner-declarations": "error",
- "no-invalid-regexp": "error",
- "no-invalid-this": "off",
- "no-irregular-whitespace": "error",
- "no-iterator": "off",
- "no-label-var": "off",
- "no-labels": "off",
- "no-lone-blocks": "off",
- "no-lonely-if": "off",
- "no-loop-func": "off",
- "no-magic-numbers": "off",
- "no-misleading-character-class": "off",
- "no-mixed-operators": "off",
- "no-mixed-requires": "off",
- "no-mixed-spaces-and-tabs": "error",
- "no-multi-assign": "off",
- "no-multi-spaces": "off",
- "no-multi-str": "off",
- "no-multiple-empty-lines": "off",
- "no-native-reassign": "off",
- "no-negated-condition": "off",
- "no-negated-in-lhs": "off",
- "no-nested-ternary": "off",
- "no-new": "off",
- "no-new-func": "off",
- "no-new-object": "off",
- "no-new-require": "off",
- "no-new-symbol": "error",
- "no-new-wrappers": "off",
- "no-obj-calls": "error",
- "no-octal": "error",
- "no-octal-escape": "off",
- "no-param-reassign": "off",
- "no-path-concat": "off",
- "no-plusplus": "off",
- "no-process-env": "off",
- "no-process-exit": "off",
- "no-proto": "off",
- "no-prototype-builtins": "off",
- "no-redeclare": "error",
- "no-regex-spaces": "error",
- "no-restricted-globals": "off",
- "no-restricted-imports": "off",
- "no-restricted-modules": "off",
- "no-restricted-properties": "off",
- "no-restricted-syntax": "off",
- "no-return-assign": "off",
- "no-return-await": "off",
- "no-script-url": "off",
- "no-self-assign": "error",
- "no-self-compare": "off",
- "no-sequences": "off",
- "no-shadow": "off",
- "no-shadow-restricted-names": "off",
- "no-spaced-func": "off",
- "no-sparse-arrays": "error",
- "no-sync": "off",
- "no-tabs": "off",
- "no-template-curly-in-string": "off",
- "no-ternary": "off",
- "no-this-before-super": "error",
- "no-throw-literal": "off",
- "no-trailing-spaces": "off",
- "no-undef": "error",
- "no-undef-init": "off",
- "no-undefined": "off",
- "no-underscore-dangle": "off",
- "no-unexpected-multiline": "error",
- "no-unmodified-loop-condition": "off",
- "no-unneeded-ternary": "off",
- "no-unreachable": "error",
- "no-unsafe-finally": "error",
- "no-unsafe-negation": "error",
- "no-unused-expressions": "off",
- "no-unused-labels": "error",
- "no-unused-vars": "error",
- "no-use-before-define": "off",
- "no-useless-call": "off",
- "no-useless-catch": "off",
- "no-useless-computed-key": "off",
- "no-useless-concat": "off",
- "no-useless-constructor": "off",
- "no-useless-escape": "error",
- "no-useless-rename": "off",
- "no-useless-return": "off",
- "no-var": "off",
- "no-void": "off",
- "no-warning-comments": "off",
- "no-whitespace-before-property": "off",
- "no-with": "off",
- "nonblock-statement-body-position": "off",
- "object-curly-newline": "off",
- "object-curly-spacing": "off",
- "object-property-newline": "off",
- "object-shorthand": "off",
- "one-var": "off",
- "one-var-declaration-per-line": "off",
- "operator-assignment": "off",
- "operator-linebreak": "off",
- "padded-blocks": "off",
- "padding-line-between-statements": "off",
- "prefer-arrow-callback": "off",
- "prefer-const": "off",
- "prefer-destructuring": "off",
- "prefer-numeric-literals": "off",
- "prefer-object-spread": "off",
- "prefer-promise-reject-errors": "off",
- "prefer-reflect": "off",
- "prefer-rest-params": "off",
- "prefer-spread": "off",
- "prefer-template": "off",
- "quote-props": "off",
- quotes: "off",
- radix: "off",
- "require-atomic-updates": "off",
- "require-await": "off",
- "require-jsdoc": "off",
- "require-unicode-regexp": "off",
- "require-yield": "error",
- "rest-spread-spacing": "off",
- semi: "off",
- "semi-spacing": "off",
- "semi-style": "off",
- "sort-imports": "off",
- "sort-keys": "off",
- "sort-vars": "off",
- "space-before-blocks": "off",
- "space-before-function-paren": "off",
- "space-in-parens": "off",
- "space-infix-ops": "off",
- "space-unary-ops": "off",
- "spaced-comment": "off",
- strict: "off",
- "switch-colon-spacing": "off",
- "symbol-description": "off",
- "template-curly-spacing": "off",
- "template-tag-spacing": "off",
- "unicode-bom": "off",
- "use-isnan": "error",
- "valid-jsdoc": "off",
- "valid-typeof": "error",
- "vars-on-top": "off",
- "wrap-iife": "off",
- "wrap-regex": "off",
- "yield-star-spacing": "off",
- yoda: "off"
- }
+ rules: Object.assign({}, ...Object.keys(builtInRules).map(ruleId => ({
+ [ruleId]: builtInRules[ruleId].meta.docs.recommended ? "error" : "off"
+ })))
};

lib/built-in-rules-index.js

@@ -0,0 +1,278 @@
+/**
+ * @fileoverview Collects the built-in rules into a map structure so that they can be imported all at once and without
+ * using the file-system directly.
+ * @author Peter (Somogyvari) Metz
+ */
+
+"use strict";
+
+/* eslint sort-keys: ["error", "asc"] */
+
+module.exports = {
+ "accessor-pairs": require("./rules/accessor-pairs"),
+ "array-bracket-newline": require("./rules/array-bracket-newline"),
+ "array-bracket-spacing": require("./rules/array-bracket-spacing"),
+ "array-callback-return": require("./rules/array-callback-return"),
+ "array-element-newline": require("./rules/array-element-newline"),
+ "arrow-body-style": require("./rules/arrow-body-style"),
+ "arrow-parens": require("./rules/arrow-parens"),
+ "arrow-spacing": require("./rules/arrow-spacing"),
+ "block-scoped-var": require("./rules/block-scoped-var"),
+ "block-spacing": require("./rules/block-spacing"),
+ "brace-style": require("./rules/brace-style"),
+ "callback-return": require("./rules/callback-return"),
+ camelcase: require("./rules/camelcase"),
+ "capitalized-comments": require("./rules/capitalized-comments"),
+ "class-methods-use-this": require("./rules/class-methods-use-this"),
+ "comma-dangle": require("./rules/comma-dangle"),
+ "comma-spacing": require("./rules/comma-spacing"),
+ "comma-style": require("./rules/comma-style"),
+ complexity: require("./rules/complexity"),
+ "computed-property-spacing": require("./rules/computed-property-spacing"),
+ "consistent-return": require("./rules/consistent-return"),
+ "consistent-this": require("./rules/consistent-this"),
+ "constructor-super": require("./rules/constructor-super"),
+ curly: require("./rules/curly"),
+ "default-case": require("./rules/default-case"),
+ "dot-location": require("./rules/dot-location"),
+ "dot-notation": require("./rules/dot-notation"),
+ "eol-last": require("./rules/eol-last"),
+ eqeqeq: require("./rules/eqeqeq"),
+ "for-direction": require("./rules/for-direction"),
+ "func-call-spacing": require("./rules/func-call-spacing"),
+ "func-name-matching": require("./rules/func-name-matching"),
+ "func-names": require("./rules/func-names"),
+ "func-style": require("./rules/func-style"),
+ "function-paren-newline": require("./rules/function-paren-newline"),
+ "generator-star-spacing": require("./rules/generator-star-spacing"),
+ "getter-return": require("./rules/getter-return"),
+ "global-require": require("./rules/global-require"),
+ "guard-for-in": require("./rules/guard-for-in"),
+ "handle-callback-err": require("./rules/handle-callback-err"),
+ "id-blacklist": require("./rules/id-blacklist"),
+ "id-length": require("./rules/id-length"),
+ "id-match": require("./rules/id-match"),
+ "implicit-arrow-linebreak": require("./rules/implicit-arrow-linebreak"),
+ indent: require("./rules/indent"),
+ "indent-legacy": require("./rules/indent-legacy"),
+ "init-declarations": require("./rules/init-declarations"),
+ "jsx-quotes": require("./rules/jsx-quotes"),
+ "key-spacing": require("./rules/key-spacing"),
+ "keyword-spacing": require("./rules/keyword-spacing"),
+ "line-comment-position": require("./rules/line-comment-position"),
+ "linebreak-style": require("./rules/linebreak-style"),
+ "lines-around-comment": require("./rules/lines-around-comment"),
+ "lines-around-directive": require("./rules/lines-around-directive"),
+ "lines-between-class-members": require("./rules/lines-between-class-members"),
+ "max-classes-per-file": require("./rules/max-classes-per-file"),
+ "max-depth": require("./rules/max-depth"),
+ "max-len": require("./rules/max-len"),
+ "max-lines": require("./rules/max-lines"),
+ "max-lines-per-function": require("./rules/max-lines-per-function"),
+ "max-nested-callbacks": require("./rules/max-nested-callbacks"),
+ "max-params": require("./rules/max-params"),
+ "max-statements": require("./rules/max-statements"),
+ "max-statements-per-line": require("./rules/max-statements-per-line"),
+ "multiline-comment-style": require("./rules/multiline-comment-style"),
+ "multiline-ternary": require("./rules/multiline-ternary"),
+ "new-cap": require("./rules/new-cap"),
+ "new-parens": require("./rules/new-parens"),
+ "newline-after-var": require("./rules/newline-after-var"),
+ "newline-before-return": require("./rules/newline-before-return"),
+ "newline-per-chained-call": require("./rules/newline-per-chained-call"),
+ "no-alert": require("./rules/no-alert"),
+ "no-array-constructor": require("./rules/no-array-constructor"),
+ "no-async-promise-executor": require("./rules/no-async-promise-executor"),
+ "no-await-in-loop": require("./rules/no-await-in-loop"),
+ "no-bitwise": require("./rules/no-bitwise"),
+ "no-buffer-constructor": require("./rules/no-buffer-constructor"),
+ "no-caller": require("./rules/no-caller"),
+ "no-case-declarations": require("./rules/no-case-declarations"),
+ "no-catch-shadow": require("./rules/no-catch-shadow"),
+ "no-class-assign": require("./rules/no-class-assign"),
+ "no-compare-neg-zero": require("./rules/no-compare-neg-zero"),
+ "no-cond-assign": require("./rules/no-cond-assign"),
+ "no-confusing-arrow": require("./rules/no-confusing-arrow"),
+ "no-console": require("./rules/no-console"),
+ "no-const-assign": require("./rules/no-const-assign"),
+ "no-constant-condition": require("./rules/no-constant-condition"),
+ "no-continue": require("./rules/no-continue"),
+ "no-control-regex": require("./rules/no-control-regex"),
+ "no-debugger": require("./rules/no-debugger"),
+ "no-delete-var": require("./rules/no-delete-var"),
+ "no-div-regex": require("./rules/no-div-regex"),
+ "no-dupe-args": require("./rules/no-dupe-args"),
+ "no-dupe-class-members": require("./rules/no-dupe-class-members"),
+ "no-dupe-keys": require("./rules/no-dupe-keys"),
+ "no-duplicate-case": require("./rules/no-duplicate-case"),
+ "no-duplicate-imports": require("./rules/no-duplicate-imports"),
+ "no-else-return": require("./rules/no-else-return"),
+ "no-empty": require("./rules/no-empty"),
+ "no-empty-character-class": require("./rules/no-empty-character-class"),
+ "no-empty-function": require("./rules/no-empty-function"),
+ "no-empty-pattern": require("./rules/no-empty-pattern"),
+ "no-eq-null": require("./rules/no-eq-null"),
+ "no-eval": require("./rules/no-eval"),
+ "no-ex-assign": require("./rules/no-ex-assign"),
+ "no-extend-native": require("./rules/no-extend-native"),
+ "no-extra-bind": require("./rules/no-extra-bind"),
+ "no-extra-boolean-cast": require("./rules/no-extra-boolean-cast"),
+ "no-extra-label": require("./rules/no-extra-label"),
+ "no-extra-parens": require("./rules/no-extra-parens"),
+ "no-extra-semi": require("./rules/no-extra-semi"),
+ "no-fallthrough": require("./rules/no-fallthrough"),
+ "no-floating-decimal": require("./rules/no-floating-decimal"),
+ "no-func-assign": require("./rules/no-func-assign"),
+ "no-global-assign": require("./rules/no-global-assign"),
+ "no-implicit-coercion": require("./rules/no-implicit-coercion"),
+ "no-implicit-globals": require("./rules/no-implicit-globals"),
+ "no-implied-eval": require("./rules/no-implied-eval"),
+ "no-inline-comments": require("./rules/no-inline-comments"),
+ "no-inner-declarations": require("./rules/no-inner-declarations"),
+ "no-invalid-regexp": require("./rules/no-invalid-regexp"),
+ "no-invalid-this": require("./rules/no-invalid-this"),
+ "no-irregular-whitespace": require("./rules/no-irregular-whitespace"),
+ "no-iterator": require("./rules/no-iterator"),
+ "no-label-var": require("./rules/no-label-var"),
+ "no-labels": require("./rules/no-labels"),
+ "no-lone-blocks": require("./rules/no-lone-blocks"),
+ "no-lonely-if": require("./rules/no-lonely-if"),
+ "no-loop-func": require("./rules/no-loop-func"),
+ "no-magic-numbers": require("./rules/no-magic-numbers"),
+ "no-misleading-character-class": require("./rules/no-misleading-character-class"),
+ "no-mixed-operators": require("./rules/no-mixed-operators"),
+ "no-mixed-requires": require("./rules/no-mixed-requires"),
+ "no-mixed-spaces-and-tabs": require("./rules/no-mixed-spaces-and-tabs"),
+ "no-multi-assign": require("./rules/no-multi-assign"),
+ "no-multi-spaces": require("./rules/no-multi-spaces"),
+ "no-multi-str": require("./rules/no-multi-str"),
+ "no-multiple-empty-lines": require("./rules/no-multiple-empty-lines"),
+ "no-native-reassign": require("./rules/no-native-reassign"),
+ "no-negated-condition": require("./rules/no-negated-condition"),
+ "no-negated-in-lhs": require("./rules/no-negated-in-lhs"),
+ "no-nested-ternary": require("./rules/no-nested-ternary"),
+ "no-new": require("./rules/no-new"),
+ "no-new-func": require("./rules/no-new-func"),
+ "no-new-object": require("./rules/no-new-object"),
+ "no-new-require": require("./rules/no-new-require"),
+ "no-new-symbol": require("./rules/no-new-symbol"),
+ "no-new-wrappers": require("./rules/no-new-wrappers"),
+ "no-obj-calls": require("./rules/no-obj-calls"),
+ "no-octal": require("./rules/no-octal"),
+ "no-octal-escape": require("./rules/no-octal-escape"),
+ "no-param-reassign": require("./rules/no-param-reassign"),
+ "no-path-concat": require("./rules/no-path-concat"),
+ "no-plusplus": require("./rules/no-plusplus"),
+ "no-process-env": require("./rules/no-process-env"),
+ "no-process-exit": require("./rules/no-process-exit"),
+ "no-proto": require("./rules/no-proto"),
+ "no-prototype-builtins": require("./rules/no-prototype-builtins"),
+ "no-redeclare": require("./rules/no-redeclare"),
+ "no-regex-spaces": require("./rules/no-regex-spaces"),
+ "no-restricted-globals": require("./rules/no-restricted-globals"),
+ "no-restricted-imports": require("./rules/no-restricted-imports"),
+ "no-restricted-modules": require("./rules/no-restricted-modules"),
+ "no-restricted-properties": require("./rules/no-restricted-properties"),
+ "no-restricted-syntax": require("./rules/no-restricted-syntax"),
+ "no-return-assign": require("./rules/no-return-assign"),
+ "no-return-await": require("./rules/no-return-await"),
+ "no-script-url": require("./rules/no-script-url"),
+ "no-self-assign": require("./rules/no-self-assign"),
+ "no-self-compare": require("./rules/no-self-compare"),
+ "no-sequences": require("./rules/no-sequences"),
+ "no-shadow": require("./rules/no-shadow"),
+ "no-shadow-restricted-names": require("./rules/no-shadow-restricted-names"),
+ "no-spaced-func": require("./rules/no-spaced-func"),
+ "no-sparse-arrays": require("./rules/no-sparse-arrays"),
+ "no-sync": require("./rules/no-sync"),
+ "no-tabs": require("./rules/no-tabs"),
+ "no-template-curly-in-string": require("./rules/no-template-curly-in-string"),
+ "no-ternary": require("./rules/no-ternary"),
+ "no-this-before-super": require("./rules/no-this-before-super"),
+ "no-throw-literal": require("./rules/no-throw-literal"),
+ "no-trailing-spaces": require("./rules/no-trailing-spaces"),
+ "no-undef": require("./rules/no-undef"),
+ "no-undef-init": require("./rules/no-undef-init"),
+ "no-undefined": require("./rules/no-undefined"),
+ "no-underscore-dangle": require("./rules/no-underscore-dangle"),
+ "no-unexpected-multiline": require("./rules/no-unexpected-multiline"),
+ "no-unmodified-loop-condition": require("./rules/no-unmodified-loop-condition"),
+ "no-unneeded-ternary": require("./rules/no-unneeded-ternary"),
+ "no-unreachable": require("./rules/no-unreachable"),
+ "no-unsafe-finally": require("./rules/no-unsafe-finally"),
+ "no-unsafe-negation": require("./rules/no-unsafe-negation"),
+ "no-unused-expressions": require("./rules/no-unused-expressions"),
+ "no-unused-labels": require("./rules/no-unused-labels"),
+ "no-unused-vars": require("./rules/no-unused-vars"),
+ "no-use-before-define": require("./rules/no-use-before-define"),
+ "no-useless-call": require("./rules/no-useless-call"),
+ "no-useless-catch": require("./rules/no-useless-catch"),
+ "no-useless-computed-key": require("./rules/no-useless-computed-key"),
+ "no-useless-concat": require("./rules/no-useless-concat"),
+ "no-useless-constructor": require("./rules/no-useless-constructor"),
+ "no-useless-escape": require("./rules/no-useless-escape"),
+ "no-useless-rename": require("./rules/no-useless-rename"),
+ "no-useless-return": require("./rules/no-useless-return"),
+ "no-var": require("./rules/no-var"),
+ "no-void": require("./rules/no-void"),
+ "no-warning-comments": require("./rules/no-warning-comments"),
+ "no-whitespace-before-property": require("./rules/no-whitespace-before-property"),
+ "no-with": require("./rules/no-with"),
+ "nonblock-statement-body-position": require("./rules/nonblock-statement-body-position"),
+ "object-curly-newline": require("./rules/object-curly-newline"),
+ "object-curly-spacing": require("./rules/object-curly-spacing"),
+ "object-property-newline": require("./rules/object-property-newline"),
+ "object-shorthand": require("./rules/object-shorthand"),
+ "one-var": require("./rules/one-var"),
+ "one-var-declaration-per-line": require("./rules/one-var-declaration-per-line"),
+ "operator-assignment": require("./rules/operator-assignment"),
+ "operator-linebreak": require("./rules/operator-linebreak"),
+ "padded-blocks": require("./rules/padded-blocks"),
+ "padding-line-between-statements": require("./rules/padding-line-between-statements"),
+ "prefer-arrow-callback": require("./rules/prefer-arrow-callback"),
+ "prefer-const": require("./rules/prefer-const"),
+ "prefer-destructuring": require("./rules/prefer-destructuring"),
+ "prefer-named-capture-group": require("./rules/prefer-named-capture-group"),
+ "prefer-numeric-literals": require("./rules/prefer-numeric-literals"),
+ "prefer-object-spread": require("./rules/prefer-object-spread"),
+ "prefer-promise-reject-errors": require("./rules/prefer-promise-reject-errors"),
+ "prefer-reflect": require("./rules/prefer-reflect"),
+ "prefer-rest-params": require("./rules/prefer-rest-params"),
+ "prefer-spread": require("./rules/prefer-spread"),
+ "prefer-template": require("./rules/prefer-template"),
+ "quote-props": require("./rules/quote-props"),
+ quotes: require("./rules/quotes"),
+ radix: require("./rules/radix"),
+ "require-atomic-updates": require("./rules/require-atomic-updates"),
+ "require-await": require("./rules/require-await"),
+ "require-jsdoc": require("./rules/require-jsdoc"),
+ "require-unicode-regexp": require("./rules/require-unicode-regexp"),
+ "require-yield": require("./rules/require-yield"),
+ "rest-spread-spacing": require("./rules/rest-spread-spacing"),
+ semi: require("./rules/semi"),
+ "semi-spacing": require("./rules/semi-spacing"),
+ "semi-style": require("./rules/semi-style"),
+ "sort-imports": require("./rules/sort-imports"),
+ "sort-keys": require("./rules/sort-keys"),
+ "sort-vars": require("./rules/sort-vars"),
+ "space-before-blocks": require("./rules/space-before-blocks"),
+ "space-before-function-paren": require("./rules/space-before-function-paren"),
+ "space-in-parens": require("./rules/space-in-parens"),
+ "space-infix-ops": require("./rules/space-infix-ops"),
+ "space-unary-ops": require("./rules/space-unary-ops"),
+ "spaced-comment": require("./rules/spaced-comment"),
+ strict: require("./rules/strict"),
+ "switch-colon-spacing": require("./rules/switch-colon-spacing"),
+ "symbol-description": require("./rules/symbol-description"),
+ "template-curly-spacing": require("./rules/template-curly-spacing"),
+ "template-tag-spacing": require("./rules/template-tag-spacing"),
+ "unicode-bom": require("./rules/unicode-bom"),
+ "use-isnan": require("./rules/use-isnan"),
+ "valid-jsdoc": require("./rules/valid-jsdoc"),
+ "valid-typeof": require("./rules/valid-typeof"),
+ "vars-on-top": require("./rules/vars-on-top"),
+ "wrap-iife": require("./rules/wrap-iife"),
+ "wrap-regex": require("./rules/wrap-regex"),
+ "yield-star-spacing": require("./rules/yield-star-spacing"),
+ yoda: require("./rules/yoda")
+};

lib/cli-engine.js

@@ -29,7 +29,8 @@
hash = require("./util/hash"),
ModuleResolver = require("./util/module-resolver"),
naming = require("./util/naming"),
- pkg = require("../package.json");
+ pkg = require("../package.json"),
+ loadRules = require("./load-rules");
const debug = require("debug")("eslint:cli-engine");
const resolver = new ModuleResolver();
@@ -257,7 +258,7 @@
*/
function createIgnoreResult(filePath, baseDir) {
let message;
- const isHidden = /^\./.test(path.basename(filePath));
+ const isHidden = /^\./u.test(path.basename(filePath));
const isInNodeModules = baseDir && path.relative(baseDir, filePath).startsWith("node_modules");
const isInBowerComponents = baseDir && path.relative(baseDir, filePath).startsWith("bower_components");
@@ -447,13 +448,16 @@
this.options.rulePaths.forEach(rulesdir => {
debug(`Loading rules from ${rulesdir}`);
- this.linter.rules.load(rulesdir, cwd);
+ this.linter.defineRules(loadRules(rulesdir, cwd));
});
}
if (this.options.rules && Object.keys(this.options.rules).length) {
const loadedRules = this.linter.getRules();
+ // Ajv validator with default schema will mutate original object, so we must clone it recursively.
+ this.options.rules = lodash.cloneDeep(this.options.rules);
+
Object.keys(this.options.rules).forEach(name => {
validator.validateRuleOptions(loadedRules.get(name), name, this.options.rules[name], "CLI");
});
@@ -753,7 +757,7 @@
if (typeof resolvedFormatName === "string") {
// replace \ with / for Windows compatibility
- const normalizedFormatName = resolvedFormatName.replace(/\\/g, "/");
+ const normalizedFormatName = resolvedFormatName.replace(/\\/gu, "/");
const cwd = this.options ? this.options.cwd : process.cwd();
const namespace = naming.getNamespaceFromTerm(normalizedFormatName);

lib/cli.js

@@ -81,15 +81,23 @@
*/
function printResults(engine, results, format, outputFile) {
let formatter;
+ let rules;
try {
formatter = engine.getFormatter(format);
+ rules = engine.getRules();
} catch (e) {
log.error(e.message);
return false;
}
- const output = formatter(results);
+ const rulesMeta = {};
+
+ rules.forEach((rule, ruleId) => {
+ rulesMeta[ruleId] = rule.meta;
+ });
+
+ const output = formatter(results, { rulesMeta });
if (output) {
if (outputFile) {

lib/config/config-file.js

@@ -61,7 +61,7 @@
* @private
*/
function readFile(filePath) {
- return fs.readFileSync(filePath, "utf8").replace(/^\ufeff/, "");
+ return fs.readFileSync(filePath, "utf8").replace(/^\ufeff/u, "");
}
/**
@@ -73,7 +73,7 @@
* @private
*/
function isFilePath(filePath) {
- return path.isAbsolute(filePath) || !/\w|@/.test(filePath.charAt(0));
+ return path.isAbsolute(filePath) || !/\w|@/u.test(filePath.charAt(0));
}
/**
@@ -280,15 +280,38 @@
* Writes a configuration file in JavaScript format.
* @param {Object} config The configuration object to write.
* @param {string} filePath The filename to write to.
+ * @throws {Error} If an error occurs linting the config file contents.
* @returns {void}
* @private
*/
function writeJSConfigFile(config, filePath) {
debug(`Writing JS config file: ${filePath}`);
- const content = `module.exports = ${stringify(config, { cmp: sortByKey, space: 4 })};`;
+ let contentToWrite;
+ const stringifiedContent = `module.exports = ${stringify(config, { cmp: sortByKey, space: 4 })};`;
- fs.writeFileSync(filePath, content, "utf8");
+ try {
+ const CLIEngine = require("../cli-engine");
+ const linter = new CLIEngine({
+ baseConfig: config,
+ fix: true,
+ useEslintrc: false
+ });
+ const report = linter.executeOnText(stringifiedContent);
+
+ contentToWrite = report.results[0].output || stringifiedContent;
+ } catch (e) {
+ debug("Error linting JavaScript config file, writing unlinted version");
+ const errorMessage = e.message;
+
+ contentToWrite = stringifiedContent;
+ e.message = "An error occurred while generating your JavaScript config file. ";
+ e.message += "A config file was still generated, but the config file itself may not follow your linting rules.";
+ e.message += `\nError: ${errorMessage}`;
+ throw e;
+ } finally {
+ fs.writeFileSync(filePath, contentToWrite, "utf8");
+ }
}
/**
@@ -518,7 +541,7 @@
const ruleMap = configContext.linterContext.getRules();
// validate the configuration before continuing
- validator.validate(config, resolvedPath.configFullName, ruleMap.get.bind(ruleMap), configContext.linterContext.environments);
+ validator.validate(config, ruleMap.get.bind(ruleMap), configContext.linterContext.environments, resolvedPath.configFullName);
/*
* If an `extends` property is defined, it represents a configuration file to use as

lib/config/config-initializer.js

@@ -28,6 +29,8 @@
// Private
//------------------------------------------------------------------------------
+const DEFAULT_ECMA_VERSION = 2018;
+
/* istanbul ignore next: hard to test fs function */
/**
* Create .eslintrc file in the current working directory
@@ -149,7 +152,7 @@
bar.tick(0); // Shows the progress bar
// Get the SourceCode of all chosen files
- const patterns = answers.patterns.split(/[\s]+/);
+ const patterns = answers.patterns.split(/[\s]+/u);
try {
sourceCodes = getSourceCodeOfFiles(patterns, { baseConfig: newConfig, useEslintrc: false }, total => {
@@ -239,44 +242,66 @@
* @returns {Object} config object
*/
function processAnswers(answers) {
- let config = { rules: {}, env: {}, parserOptions: {} };
+ let config = {
+ rules: {},
+ env: {},
+ parserOptions: {},
+ extends: []
+ };
- config.parserOptions.ecmaVersion = answers.ecmaVersion;
- if (answers.ecmaVersion >= 2015) {
- if (answers.modules) {
- config.parserOptions.sourceType = "module";
- }
+ // set the latest ECMAScript version
+ config.parserOptions.ecmaVersion = DEFAULT_ECMA_VERSION;
config.env.es6 = true;
- }
+ config.globals = {
+ Atomics: "readonly",
+ SharedArrayBuffer: "readonly"
+ };
- if (answers.commonjs) {
+ // set the module type
+ if (answers.moduleType === "esm") {
+ config.parserOptions.sourceType = "module";
+ } else if (answers.moduleType === "commonjs") {
config.env.commonjs = true;
}
+
+ // add in browser and node environments if necessary
answers.env.forEach(env => {
config.env[env] = true;
});
- if (answers.jsx) {
- config.parserOptions = config.parserOptions || {};
- config.parserOptions.ecmaFeatures = config.parserOptions.ecmaFeatures || {};
- config.parserOptions.ecmaFeatures.jsx = true;
- if (answers.react) {
+
+ // add in library information
+ if (answers.framework === "react") {
+ config.parserOptions.ecmaFeatures = {
+ jsx: true
+ };
config.plugins = ["react"];
- config.parserOptions.ecmaVersion = 2018;
- }
+ } else if (answers.framework === "vue") {
+ config.plugins = ["vue"];
+ config.extends.push("plugin:vue/essential");
}
+ // setup rules based on problems/style enforcement preferences
+ if (answers.purpose === "problems") {
+ config.extends.unshift("eslint:recommended");
+ } else if (answers.purpose === "style") {
if (answers.source === "prompt") {
- config.extends = "eslint:recommended";
+ config.extends.unshift("eslint:recommended");
config.rules.indent = ["error", answers.indent];
config.rules.quotes = ["error", answers.quotes];
config.rules["linebreak-style"] = ["error", answers.linebreak];
config.rules.semi = ["error", answers.semi ? "always" : "never"];
- }
-
- if (answers.source === "auto") {
+ } else if (answers.source === "auto") {
config = configureRules(answers, config);
config = autoconfig.extendFromRecommended(config);
}
+ }
+
+ // normalize extends
+ if (config.extends.length === 0) {
+ delete config.extends;
+ } else if (config.extends.length === 1) {
+ config.extends = config.extends[0];
+ }
ConfigOps.normalizeToStrings(config);
return config;
@@ -324,7 +349,7 @@
* @returns {string} The shareable config name.
*/
function getStyleGuideName(answers) {
- if (answers.styleguide === "airbnb" && !answers.airbnbReact) {
+ if (answers.styleguide === "airbnb" && answers.framework !== "react") {
return "airbnb-base";
}
return answers.styleguide;
@@ -419,14 +444,60 @@
return inquirer.prompt([
{
type: "list",
+ name: "purpose",
+ message: "How would you like to use ESLint?",
+ default: "problems",
+ choices: [
+ { name: "To check syntax only", value: "syntax" },
+ { name: "To check syntax and find problems", value: "problems" },
+ { name: "To check syntax, find problems, and enforce code style", value: "style" }
+ ]
+ },
+ {
+ type: "list",
+ name: "moduleType",
+ message: "What type of modules does your project use?",
+ default: "esm",
+ choices: [
+ { name: "JavaScript modules (import/export)", value: "esm" },
+ { name: "CommonJS (require/exports)", value: "commonjs" },
+ { name: "None of these", value: "none" }
+ ]
+ },
+ {
+ type: "list",
+ name: "framework",
+ message: "Which framework does your project use?",
+ default: "react",
+ choices: [
+ { name: "React", value: "react" },
+ { name: "Vue.js", value: "vue" },
+ { name: "None of these", value: "none" }
+ ]
+ },
+ {
+ type: "checkbox",
+ name: "env",
+ message: "Where does your code run?",
+ default: ["browser"],
+ choices: [
+ { name: "Browser", value: "browser" },
+ { name: "Node", value: "node" }
+ ]
+ },
+ {
+ type: "list",
name: "source",
- message: "How would you like to configure ESLint?",
- default: "prompt",
+ message: "How would you like to define a style for your project?",
+ default: "guide",
choices: [
{ name: "Use a popular style guide", value: "guide" },
{ name: "Answer questions about your style", value: "prompt" },
{ name: "Inspect your JavaScript file(s)", value: "auto" }
- ]
+ ],
+ when(answers) {
+ return answers.purpose === "style";
+ }
},
{
type: "list",
@@ -443,15 +514,6 @@
}
},
{
- type: "confirm",
- name: "airbnbReact",
- message: "Do you use React?",
- default: false,
- when(answers) {
- return answers.styleguide === "airbnb";
- }
- },
- {
type: "input",
name: "patterns",
message: "Which file(s), path(s), or glob(s) should be examined?",
@@ -470,10 +532,7 @@
name: "format",
message: "What format do you want your config file to be in?",
default: "JavaScript",
- choices: ["JavaScript", "YAML", "JSON"],
- when(answers) {
- return ((answers.source === "guide" && answers.packageJsonExists) || answers.source === "auto");
- }
+ choices: ["JavaScript", "YAML", "JSON"]
},
{
type: "confirm",
@@ -492,6 +551,15 @@
}
]).then(earlyAnswers => {
+ // early exit if no style guide is necessary
+ if (earlyAnswers.purpose !== "style") {
+ const config = processAnswers(earlyAnswers);
+ const modules = getModulesList(config);
+
+ return askInstallModules(modules, earlyAnswers.packageJsonExists)
+ .then(() => writeFile(config, earlyAnswers.format));
+ }
+
// early exit if you are using a style guide
if (earlyAnswers.source === "guide") {
if (!earlyAnswers.packageJsonExists) {
@@ -501,81 +569,21 @@
if (earlyAnswers.installESLint === false && !semver.satisfies(earlyAnswers.localESLintVersion, earlyAnswers.requiredESLintVersionRange)) {
log.info(`Note: it might not work since ESLint's version is mismatched with the ${earlyAnswers.styleguide} config.`);
}
- if (earlyAnswers.styleguide === "airbnb" && !earlyAnswers.airbnbReact) {
+ if (earlyAnswers.styleguide === "airbnb" && earlyAnswers.framework !== "react") {
earlyAnswers.styleguide = "airbnb-base";
}
- const config = getConfigForStyleGuide(earlyAnswers.styleguide);
+ const config = ConfigOps.merge(processAnswers(earlyAnswers), getConfigForStyleGuide(earlyAnswers.styleguide));
const modules = getModulesList(config);
return askInstallModules(modules, earlyAnswers.packageJsonExists)
.then(() => writeFile(config, earlyAnswers.format));
- }
- // continue with the questions otherwise...
- return inquirer.prompt([
- {
- type: "list",
- name: "ecmaVersion",
- message: "Which version of ECMAScript do you use?",
- choices: [
- { name: "ES3", value: 3 },
- { name: "ES5", value: 5 },
- { name: "ES2015", value: 2015 },
- { name: "ES2016", value: 2016 },
- { name: "ES2017", value: 2017 },
- { name: "ES2018", value: 2018 }
- ],
- default: 1 // This is the index in the choices list
- },
- {
- type: "confirm",
- name: "modules",
- message: "Are you using ES6 modules?",
- default: false,
- when(answers) {
- return answers.ecmaVersion >= 2015;
}
- },
- {
- type: "checkbox",
- name: "env",
- message: "Where will your code run?",
- default: ["browser"],
- choices: [{ name: "Browser", value: "browser" }, { name: "Node", value: "node" }]
- },
- {
- type: "confirm",
- name: "commonjs",
- message: "Do you use CommonJS?",
- default: false,
- when(answers) {
- return answers.env.some(env => env === "browser");
- }
- },
- {
- type: "confirm",
- name: "jsx",
- message: "Do you use JSX?",
- default: false
- },
- {
- type: "confirm",
- name: "react",
- message: "Do you use React?",
- default: false,
- when(answers) {
- return answers.jsx;
- }
- }
- ]).then(secondAnswers => {
- // early exit if you are using automatic style generation
if (earlyAnswers.source === "auto") {
- const combinedAnswers = Object.assign({}, earlyAnswers, secondAnswers);
-
+ const combinedAnswers = Object.assign({}, earlyAnswers);
const config = processAnswers(combinedAnswers);
-
const modules = getModulesList(config);
return askInstallModules(modules).then(() => writeFile(config, earlyAnswers.format));
@@ -618,7 +626,7 @@
choices: ["JavaScript", "YAML", "JSON"]
}
]).then(answers => {
- const totalAnswers = Object.assign({}, earlyAnswers, secondAnswers, answers);
+ const totalAnswers = Object.assign({}, earlyAnswers, answers);
const config = processAnswers(totalAnswers);
const modules = getModulesList(config);
@@ -626,7 +634,6 @@
return askInstallModules(modules).then(() => writeFile(config, answers.format));
});
});
- });
}
//------------------------------------------------------------------------------

lib/config/config-ops.js

@@ -370,5 +370,35 @@
return patternList.some(pattern => minimatch(filePath, pattern, opts)) &&
!excludedPatternList.some(excludedPattern => minimatch(filePath, excludedPattern, opts));
+ },
+
+ /**
+ * Normalizes a value for a global in a config
+ * @param {(boolean|string|null)} configuredValue The value given for a global in configuration or in
+ * a global directive comment
+ * @returns {("readable"|"writeable"|"off")} The value normalized as a string
+ */
+ normalizeConfigGlobal(configuredValue) {
+ switch (configuredValue) {
+ case "off":
+ return "off";
+
+ case true:
+ case "true":
+ case "writeable":
+ case "writable":
+ return "writeable";
+
+ case null:
+ case false:
+ case "false":
+ case "readable":
+ case "readonly":
+ return "readable";
+
+ // Fallback to minimize compatibility impact
+ default:
+ return "writeable";
+ }
}
};

lib/config/config-rule.js

@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
const Rules = require("../rules"),
- loadRules = require("../load-rules");
+ builtInRules = require("../built-in-rules-index");
const rules = new Rules();
@@ -299,9 +299,7 @@
* @returns {rulesConfig} Hash of rule names and arrays of possible configurations
*/
function createCoreRuleConfigs() {
- const ruleList = loadRules();
-
- return Object.keys(ruleList).reduce((accumulator, id) => {
+ return Object.keys(builtInRules).reduce((accumulator, id) => {
const rule = rules.get(id);
const schema = (typeof rule === "function") ? rule.schema : rule.meta.schema;

lib/config/config-validator.js

@@ -76,7 +76,7 @@
return normSeverity;
}
- throw new Error(`\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '${util.inspect(severity).replace(/'/g, "\"").replace(/\n/g, "")}').\n`);
+ throw new Error(`\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '${util.inspect(severity).replace(/'/gu, "\"").replace(/\n/gu, "")}').\n`);
}
@@ -116,7 +116,7 @@
* no source is prepended to the message.
* @returns {void}
*/
-function validateRuleOptions(rule, ruleId, options, source) {
+function validateRuleOptions(rule, ruleId, options, source = null) {
if (!rule) {
return;
}
@@ -140,11 +140,11 @@
/**
* Validates an environment object
* @param {Object} environment The environment config object to validate.
- * @param {string} source The name of the configuration source to report in any errors.
* @param {Environments} envContext Env context
+ * @param {string} source The name of the configuration source to report in any errors.
* @returns {void}
*/
-function validateEnvironment(environment, source, envContext) {
+function validateEnvironment(environment, envContext, source = null) {
// not having an environment is ok
if (!environment) {
@@ -163,11 +163,11 @@
/**
* Validates a rules config object
* @param {Object} rulesConfig The rules config object to validate.
- * @param {string} source The name of the configuration source to report in any errors.
* @param {function(string): {create: Function}} ruleMapper A mapper function from strings to loaded rules
+ * @param {string} source The name of the configuration source to report in any errors.
* @returns {void}
*/
-function validateRules(rulesConfig, source, ruleMapper) {
+function validateRules(rulesConfig, ruleMapper, source = null) {
if (!rulesConfig) {
return;
}
@@ -228,7 +228,7 @@
* @param {string} source The name of the configuration source to report in any errors.
* @returns {void}
*/
-function validateConfigSchema(config, source) {
+function validateConfigSchema(config, source = null) {
validateSchema = validateSchema || ajv.compile(configSchema);
if (!validateSchema(config)) {
@@ -252,19 +252,19 @@
/**
* Validates an entire config object.
* @param {Object} config The config object to validate.
- * @param {string} source The name of the configuration source to report in any errors.
* @param {function(string): {create: Function}} ruleMapper A mapper function from rule IDs to defined rules
* @param {Environments} envContext The env context
+ * @param {string} source The name of the configuration source to report in any errors.
* @returns {void}
*/
-function validate(config, source, ruleMapper, envContext) {
+function validate(config, ruleMapper, envContext, source = null) {
validateConfigSchema(config, source);
- validateRules(config.rules, source, ruleMapper);
- validateEnvironment(config.env, source, envContext);
+ validateRules(config.rules, ruleMapper, source);
+ validateEnvironment(config.env, envContext, source);
for (const override of config.overrides || []) {
- validateRules(override.rules, source, ruleMapper);
- validateEnvironment(override.env, source, envContext);
+ validateRules(override.rules, ruleMapper, source);
+ validateEnvironment(override.env, envContext, source);
}
}

lib/config/plugins.js

@@ -24,12 +24,12 @@
/**
* Creates the plugins context
* @param {Environments} envContext - env context
- * @param {Rules} rulesContext - rules context
+ * @param {function(string, Rule): void} defineRule - Callback for when a plugin is defined which introduces rules
*/
- constructor(envContext, rulesContext) {
+ constructor(envContext, defineRule) {
this._plugins = Object.create(null);
this._environments = envContext;
- this._rules = rulesContext;
+ this._defineRule = defineRule;
}
/**
@@ -45,7 +45,15 @@
// load up environments and rules
this._plugins[shortName] = plugin;
this._environments.importPlugin(plugin, shortName);
- this._rules.importPlugin(plugin, shortName);
+
+ if (plugin.rules) {
+ Object.keys(plugin.rules).forEach(ruleId => {
+ const qualifiedRuleId = `${shortName}/${ruleId}`,
+ rule = plugin.rules[ruleId];
+
+ this._defineRule(qualifiedRuleId, rule);
+ });
+ }
}
/**
@@ -76,7 +84,7 @@
const shortName = naming.getShorthandName(longName, "eslint-plugin");
let plugin = null;
- if (pluginName.match(/\s+/)) {
+ if (pluginName.match(/\s+/u)) {
const whitespaceError = new Error(`Whitespace found in plugin name '${pluginName}'`);
whitespaceError.messageTemplate = "whitespace-found";

lib/config.js

@@ -71,7 +71,7 @@
const options = providedOptions || {};
this.linterContext = linterContext;
- this.plugins = new Plugins(linterContext.environments, linterContext.rules);
+ this.plugins = new Plugins(linterContext.environments, linterContext.defineRule.bind(linterContext));
this.options = options;
this.ignore = options.ignore;

lib/formatters/codeframe.js

@@ -47,7 +47,7 @@
*/
function formatMessage(message, parentResult) {
const type = (message.fatal || message.severity === 2) ? chalk.red("error") : chalk.yellow("warning");
- const msg = `${chalk.bold(message.message.replace(/([^ ])\.$/, "$1"))}`;
+ const msg = `${chalk.bold(message.message.replace(/([^ ])\.$/u, "$1"))}`;
const ruleId = message.fatal ? "" : chalk.dim(`(${message.ruleId})`);
const filePath = formatFilePath(parentResult.filePath, message.line, message.column);
const sourceCode = parentResult.output ? parentResult.output : parentResult.source;

lib/formatters/html.js

@@ -62,9 +62,10 @@
* Get HTML (table rows) describing the messages.
* @param {Array} messages Messages.
* @param {int} parentIndex Index of the parent HTML row.
+ * @param {Object} rulesMeta Dictionary containing metadata for each rule executed by the analysis.
* @returns {string} HTML (table rows) describing the messages.
*/
-function renderMessages(messages, parentIndex) {
+function renderMessages(messages, parentIndex, rulesMeta) {
/**
* Get HTML (table row) describing a message.
@@ -74,6 +75,13 @@
return lodash.map(messages, message => {
const lineNumber = message.line || 0;
const columnNumber = message.column || 0;
+ let ruleUrl;
+
+ if (rulesMeta) {
+ const meta = rulesMeta[message.ruleId];
+
+ ruleUrl = lodash.get(meta, "docs.url", null);
+ }
return messageTemplate({
parentIndex,
@@ -82,33 +90,37 @@
severityNumber: message.severity,
severityName: message.severity === 1 ? "Warning" : "Error",
message: message.message,
- ruleId: message.ruleId
+ ruleId: message.ruleId,
+ ruleUrl
});
}).join("\n");
}
/**
* @param {Array} results Test results.
+ * @param {Object} rulesMeta Dictionary containing metadata for each rule executed by the analysis.
* @returns {string} HTML string describing the results.
*/
-function renderResults(results) {
+function renderResults(results, rulesMeta) {
return lodash.map(results, (result, index) => resultTemplate({
index,
color: renderColor(result.errorCount, result.warningCount),
filePath: result.filePath,
summary: renderSummary(result.errorCount, result.warningCount)
- }) + renderMessages(result.messages, index)).join("\n");
+ }) + renderMessages(result.messages, index, rulesMeta)).join("\n");
}
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
-module.exports = function(results) {
+module.exports = function(results, data) {
let totalErrors,
totalWarnings;
+ const metaData = data ? data.rulesMeta : {};
+
totalErrors = 0;
totalWarnings = 0;
@@ -122,6 +134,6 @@
date: new Date(),
reportColor: renderColor(totalErrors, totalWarnings),
reportSummary: renderSummary(totalErrors, totalWarnings),
- results: renderResults(results)
+ results: renderResults(results, metaData)
});
};

lib/formatters/html-template-message.html

@@ -3,6 +3,6 @@
<td class="clr-<%= severityNumber %>"><%= severityName %></td>
<td><%- message %></td>
<td>
- <a href="https://eslint.org/docs/rules/<%= ruleId %>" target="_blank" rel="noopener noreferrer"><%= ruleId %></a>
+ <a href="<%= ruleUrl %>" target="_blank" rel="noopener noreferrer"><%= ruleId %></a>
</td>
</tr>

lib/formatters/json-with-metadata.js

@@ -0,0 +1,16 @@
+/**
+ * @fileoverview JSON reporter, including rules metadata
+ * @author Chris Meyer
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
+
+module.exports = function(results, data) {
+ return JSON.stringify({
+ results,
+ metadata: data
+ });
+};

lib/formatters/stylish.js

@@ -65,7 +65,7 @@
message.line || 0,
message.column || 0,
messageType,
- message.message.replace(/([^ ])\.$/, "$1"),
+ message.message.replace(/([^ ])\.$/u, "$1"),
chalk.dim(message.ruleId || "")
];
}),
@@ -75,7 +75,7 @@
return stripAnsi(str).length;
}
}
- ).split("\n").map(el => el.replace(/(\d+)\s+(\d+)/, (m, p1, p2) => chalk.dim(`${p1}:${p2}`))).join("\n")}\n\n`;
+ ).split("\n").map(el => el.replace(/(\d+)\s+(\d+)/u, (m, p1, p2) => chalk.dim(`${p1}:${p2}`))).join("\n")}\n\n`;
});
const total = errorCount + warningCount;

lib/formatters/table.js

@@ -9,14 +9,23 @@
//------------------------------------------------------------------------------
const chalk = require("chalk"),
- table = require("table").table,
- pluralize = require("pluralize");
+ table = require("table").table;
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
+ * Given a word and a count, append an "s" if count is not one.
+ * @param {string} word A word.
+ * @param {number} count Quantity.
+ * @returns {string} The original word with an s on the end if count is not one.
+ */
+function pluralize(word, count) {
+ return (count === 1 ? word : `${word}s`);
+}
+
+/**
* Draws text table.
* @param {Array<Object>} messages Error messages relating to a specific file.
* @returns {string} A text table.
@@ -129,10 +138,10 @@
result += `\n${table([
[
- chalk.red(pluralize("Error", errorCount, true))
+ chalk.red(pluralize(`${errorCount} Error`, errorCount))
],
[
- chalk.yellow(pluralize("Warning", warningCount, true))
+ chalk.yellow(pluralize(`${warningCount} Warning`, warningCount))
]
], {
columns: {

lib/formatters/tap.js

@@ -50,12 +49,11 @@
let diagnostics = {};
if (messages.length > 0) {
- testResult = "not ok";
-
messages.forEach(message => {
+ const severity = getMessageType(message);
const diagnostic = {
message: message.message,
- severity: getMessageType(message),
+ severity,
data: {
line: message.line || 0,
column: message.column || 0,
@@ -63,6 +61,11 @@
}
};
+ // This ensures a warning message is not flagged as error
+ if (severity === "error") {
+ testResult = "not ok";
+ }
+
/*
* If we have multiple messages place them under a messages key
* The first error will be logged as message key

lib/linter.js

@@ -11,6 +11,7 @@
const eslintScope = require("eslint-scope"),
evk = require("eslint-visitor-keys"),
+ espree = require("espree"),
lodash = require("lodash"),
CodePathAnalyzer = require("./code-path-analysis/code-path-analyzer"),
ConfigOps = require("./config/config-ops"),
@@ -70,29 +71,29 @@
* @returns {void}
*/
function addDeclaredGlobals(globalScope, configGlobals, commentDirectives) {
- Object.keys(configGlobals).forEach(name => {
- let variable = globalScope.set.get(name);
-
- if (!variable) {
- variable = new eslintScope.Variable(name, globalScope);
- variable.eslintExplicitGlobal = false;
- globalScope.variables.push(variable);
- globalScope.set.set(name, variable);
- }
- variable.writeable = configGlobals[name];
- });
+ const mergedGlobalsInfo = Object.assign(
+ {},
+ lodash.mapValues(configGlobals, value => ({ sourceComment: null, value: ConfigOps.normalizeConfigGlobal(value) })),
+ lodash.mapValues(commentDirectives.enabledGlobals, ({ comment, value }) => ({ sourceComment: comment, value: ConfigOps.normalizeConfigGlobal(value) }))
+ );
- Object.keys(commentDirectives.enabledGlobals).forEach(name => {
+ Object.keys(mergedGlobalsInfo)
+ .filter(name => mergedGlobalsInfo[name].value !== "off")
+ .forEach(name => {
let variable = globalScope.set.get(name);
if (!variable) {
variable = new eslintScope.Variable(name, globalScope);
+ if (mergedGlobalsInfo[name].sourceComment === null) {
+ variable.eslintExplicitGlobal = false;
+ } else {
variable.eslintExplicitGlobal = true;
- variable.eslintExplicitGlobalComment = commentDirectives.enabledGlobals[name].comment;
+ variable.eslintExplicitGlobalComment = mergedGlobalsInfo[name].sourceComment;
+ }
globalScope.variables.push(variable);
globalScope.set.set(name, variable);
}
- variable.writeable = commentDirectives.enabledGlobals[name].value;
+ variable.writeable = (mergedGlobalsInfo[name].value === "writeable");
});
// mark all exported variables as such
@@ -163,7 +164,7 @@
ast.comments.filter(token => token.type !== "Shebang").forEach(comment => {
const trimmedCommentText = comment.value.trim();
- const match = /^(eslint(-\w+){0,3}|exported|globals?)(\s|$)/.exec(trimmedCommentText);
+ const match = /^(eslint(-\w+){0,3}|exported|globals?)(\s|$)/u.exec(trimmedCommentText);
if (!match) {
return;
@@ -171,7 +172,7 @@
const directiveValue = trimmedCommentText.slice(match.index + match[1].length);
- if (/^eslint-disable-(next-)?line$/.test(match[1])) {
+ if (/^eslint-disable-(next-)?line$/u.test(match[1])) {
if (comment.loc.start.line === comment.loc.end.line) {
const directiveType = match[1].slice("eslint-".length);
@@ -191,12 +192,12 @@
} else if (comment.type === "Block") {
switch (match[1]) {
case "exported":
- Object.assign(exportedVariables, commentParser.parseBooleanConfig(directiveValue, comment));
+ Object.assign(exportedVariables, commentParser.parseStringConfig(directiveValue, comment));
break;
case "globals":
case "global":
- Object.assign(enabledGlobals, commentParser.parseBooleanConfig(directiveValue, comment));
+ Object.assign(enabledGlobals, commentParser.parseStringConfig(directiveValue, comment));
break;
case "eslint-disable":
@@ -275,7 +276,7 @@
return ecmaVersion;
}
-const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)\*\//g;
+const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)\*\//gu;
/**
* Checks whether or not there is a comment which has "eslint-env *" in a given text.
@@ -497,7 +498,7 @@
} catch (ex) {
// If the message includes a leading line number, strip it:
- const message = `Parsing error: ${ex.message.replace(/^line \d+:/i, "").trim()}`;
+ const message = `Parsing error: ${ex.message.replace(/^line \d+:/iu, "").trim()}`;
return {
success: false,
@@ -746,11 +747,16 @@
nodeQueue.forEach(traversalInfo => {
currentNode = traversalInfo.node;
+ try {
if (traversalInfo.isEntering) {
eventGenerator.enterNode(currentNode);
} else {
eventGenerator.leaveNode(currentNode);
}
+ } catch (err) {
+ err.currentNode = currentNode;
+ throw err;
+ }
});
return lintingProblems;
@@ -758,6 +764,7 @@
const lastSourceCodes = new WeakMap();
const loadedParserMaps = new WeakMap();
+const ruleMaps = new WeakMap();
//------------------------------------------------------------------------------
// Public Interface
@@ -772,10 +779,11 @@
constructor() {
lastSourceCodes.set(this, null);
loadedParserMaps.set(this, new Map());
+ ruleMaps.set(this, new Rules());
this.version = pkg.version;
-
- this.rules = new Rules();
this.environments = new Environments();
+
+ this.defineParser("espree", espree);
}
/**
@@ -873,7 +881,7 @@
const sourceCode = lastSourceCodes.get(this);
const commentDirectives = options.allowInlineConfig
- ? getDirectiveComments(options.filename, sourceCode.ast, ruleId => this.rules.get(ruleId))
+ ? getDirectiveComments(options.filename, sourceCode.ast, ruleId => ruleMaps.get(this).get(ruleId))
: { configuredRules: {}, enabledGlobals: {}, exportedVariables: {}, problems: [], disableDirectives: [] };
// augment global scope with declared global variables
@@ -891,15 +899,22 @@
lintingProblems = runRules(
sourceCode,
configuredRules,
- ruleId => this.rules.get(ruleId),
+ ruleId => ruleMaps.get(this).get(ruleId),
parserOptions,
parserName,
settings,
options.filename
);
} catch (err) {
+ err.message += `\nOccurred while linting ${options.filename}`;
debug("An error occurred while traversing");
debug("Filename:", options.filename);
+ if (err.currentNode) {
+ const { line } = err.currentNode.loc.start;
+
+ debug("Line:", line);
+ err.message += `:${line}`;
+ }
debug("Parser Options:", parserOptions);
debug("Parser Path:", parserName);
debug("Settings:", settings);
@@ -957,7 +972,7 @@
* @returns {void}
*/
defineRule(ruleId, ruleModule) {
- this.rules.define(ruleId, ruleModule);
+ ruleMaps.get(this).define(ruleId, ruleModule);
}
/**
@@ -976,7 +991,7 @@
* @returns {Map} All loaded rules
*/
getRules() {
- return this.rules.getAllLoadedRules();
+ return ruleMaps.get(this).getAllLoadedRules();
}
/**

lib/load-rules.js

@@ -20,15 +20,12 @@
/**
* Load all rule modules from specified directory.
- * @param {string} [relativeRulesDir] Path to rules directory, may be relative. Defaults to `lib/rules`.
+ * @param {string} relativeRulesDir Path to rules directory, may be relative.
* @param {string} cwd Current working directory
* @returns {Object} Loaded rule modules by rule ids (file names).
*/
module.exports = function(relativeRulesDir, cwd) {
-
- const rulesDir = relativeRulesDir
- ? path.resolve(cwd, relativeRulesDir)
- : path.join(__dirname, "rules");
+ const rulesDir = path.resolve(cwd, relativeRulesDir);
// cache will help performance as IO operation are expensive
if (rulesDirCache[rulesDir]) {

lib/rules/accessor-pairs.js

@@ -85,10 +85,12 @@
type: "object",
properties: {
getWithoutSet: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
setWithoutGet: {
- type: "boolean"
+ type: "boolean",
+ default: true
}
},
additionalProperties: false

lib/rules/array-callback-return.js

@@ -17,8 +17,8 @@
// Helpers
//------------------------------------------------------------------------------
-const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/;
-const TARGET_METHODS = /^(?:every|filter|find(?:Index)?|map|reduce(?:Right)?|some|sort)$/;
+const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/u;
+const TARGET_METHODS = /^(?:every|filter|find(?:Index)?|map|reduce(?:Right)?|some|sort)$/u;
/**
* Checks a given code path segment is reachable.
@@ -155,7 +155,8 @@
type: "object",
properties: {
allowImplicit: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/arrow-body-style.js

@@ -82,7 +82,7 @@
* @returns {boolean} `true` if it changes semantics if `;` or `}` followed by the token are removed.
*/
function hasASIProblem(token) {
- return token && token.type === "Punctuator" && /^[([/`+-]/.test(token.value);
+ return token && token.type === "Punctuator" && /^[([/`+-]/u.test(token.value);
}
/**

lib/rules/arrow-parens.js

@@ -35,7 +35,8 @@
type: "object",
properties: {
requireForBlockBody: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/arrow-spacing.js

@@ -32,10 +32,12 @@
type: "object",
properties: {
before: {
- type: "boolean"
+ type: "boolean",
+ default: true
},
after: {
- type: "boolean"
+ type: "boolean",
+ default: true
}
},
additionalProperties: false
@@ -54,11 +56,10 @@
create(context) {
// merge rules with default
- const rule = { before: true, after: true },
- option = context.options[0] || {};
+ const rule = Object.assign({}, context.options[0]);
- rule.before = option.before !== false;
- rule.after = option.after !== false;
+ rule.before = rule.before !== false;
+ rule.after = rule.after !== false;
const sourceCode = context.getSourceCode();

lib/rules/brace-style.js

@@ -30,7 +30,8 @@
type: "object",
properties: {
allowSingleLine: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/camelcase.js

@@ -25,7 +25,8 @@
type: "object",
properties: {
ignoreDestructuring: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
properties: {
enum: ["always", "never"]
@@ -54,7 +55,7 @@
const options = context.options[0] || {};
let properties = options.properties || "";
- const ignoreDestructuring = options.ignoreDestructuring || false;
+ const ignoreDestructuring = options.ignoreDestructuring;
const allow = options.allow || [];
if (properties !== "always" && properties !== "never") {
@@ -89,7 +90,7 @@
*/
function isAllowed(name) {
return allow.findIndex(
- entry => name === entry || name.match(new RegExp(entry))
+ entry => name === entry || name.match(new RegExp(entry)) // eslint-disable-line require-unicode-regexp
) !== -1;
}
@@ -141,7 +142,7 @@
* private/protected identifiers, strip them before checking if underscored
*/
const name = node.name,
- nameIsUnderscored = isUnderscored(name.replace(/^_+|_+$/g, "")),
+ nameIsUnderscored = isUnderscored(name.replace(/^_+|_+$/gu, "")),
effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent;
// First, we ignore the node if it match the ignore list

lib/rules/capitalized-comments.js

@@ -16,13 +16,8 @@
//------------------------------------------------------------------------------
const DEFAULT_IGNORE_PATTERN = astUtils.COMMENTS_IGNORE_PATTERN,
- WHITESPACE = /\s/g,
- MAYBE_URL = /^\s*[^:/?#\s]+:\/\/[^?#]/, // TODO: Combine w/ max-len pattern?
- DEFAULTS = {
- ignorePattern: null,
- ignoreInlineComments: false,
- ignoreConsecutiveComments: false
- };
+ WHITESPACE = /\s/gu,
+ MAYBE_URL = /^\s*[^:/?#\s]+:\/\/[^?#]/u; // TODO: Combine w/ max-len pattern?
/*
* Base schema body for defining the basic capitalization rule, ignorePattern,
@@ -44,6 +39,11 @@
},
additionalProperties: false
};
+const DEFAULTS = {
+ ignorePattern: "",
+ ignoreInlineComments: false,
+ ignoreConsecutiveComments: false
+};
/**
* Get normalized options for either block or line comments from the given
@@ -59,11 +59,7 @@
* @param {string} which Either "line" or "block".
* @returns {Object} The normalized options.
*/
-function getNormalizedOptions(rawOptions, which) {
- if (!rawOptions) {
- return Object.assign({}, DEFAULTS);
- }
-
+function getNormalizedOptions(rawOptions = {}, which) {
return Object.assign({}, DEFAULTS, rawOptions[which] || rawOptions);
}
@@ -95,7 +91,7 @@
const ignorePatternStr = normalizedOptions[key].ignorePattern;
if (ignorePatternStr) {
- const regExp = RegExp(`^\\s*(?:${ignorePatternStr})`);
+ const regExp = RegExp(`^\\s*(?:${ignorePatternStr})`); // eslint-disable-line require-unicode-regexp
normalizedOptions[key].ignorePatternRegExp = regExp;
}
@@ -214,7 +210,7 @@
// 2. Check for custom ignore pattern.
const commentWithoutAsterisks = comment.value
- .replace(/\*/g, "");
+ .replace(/\*/gu, "");
if (options.ignorePatternRegExp && options.ignorePatternRegExp.test(commentWithoutAsterisks)) {
return true;

lib/rules/class-methods-use-this.js

@@ -38,7 +38,7 @@
}
},
create(context) {
- const config = context.options[0] ? Object.assign({}, context.options[0]) : {};
+ const config = Object.assign({}, context.options[0]);
const exceptMethods = new Set(config.exceptMethods || []);
const stack = [];

lib/rules/comma-spacing.js

@@ -28,10 +28,12 @@
type: "object",
properties: {
before: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
after: {
- type: "boolean"
+ type: "boolean",
+ default: true
}
},
additionalProperties: false
@@ -50,8 +52,8 @@
const tokensAndComments = sourceCode.tokensAndComments;
const options = {
- before: context.options[0] ? !!context.options[0].before : false,
- after: context.options[0] ? !!context.options[0].after : true
+ before: context.options[0] ? context.options[0].before : false,
+ after: context.options[0] ? context.options[0].after : true
};
//--------------------------------------------------------------------------
@@ -118,6 +120,10 @@
report(reportItem, "before", tokens.left);
}
+ if (tokens.right && astUtils.isClosingParenToken(tokens.right)) {
+ return;
+ }
+
if (tokens.right && !options.after && tokens.right.type === "Line") {
return;
}

lib/rules/complexity.js

@@ -63,13 +63,12 @@
const option = context.options[0];
let THRESHOLD = 20;
- if (typeof option === "object" && Object.prototype.hasOwnProperty.call(option, "maximum") && typeof option.maximum === "number") {
- THRESHOLD = option.maximum;
- }
- if (typeof option === "object" && Object.prototype.hasOwnProperty.call(option, "max") && typeof option.max === "number") {
- THRESHOLD = option.max;
- }
- if (typeof option === "number") {
+ if (
+ typeof option === "object" &&
+ (Object.prototype.hasOwnProperty.call(option, "maximum") || Object.prototype.hasOwnProperty.call(option, "max"))
+ ) {
+ THRESHOLD = option.maximum || option.max;
+ } else if (typeof option === "number") {
THRESHOLD = option;
}

lib/rules/consistent-return.js

@@ -66,7 +66,8 @@
type: "object",
properties: {
treatUndefinedAsUnspecified: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/curly.js

@@ -191,7 +191,7 @@
return true;
}
- if (/^[([/`+-]/.test(tokenAfter.value)) {
+ if (/^[([/`+-]/u.test(tokenAfter.value)) {
// If the next token starts with a character that would disrupt ASI, insert a semicolon.
return true;

lib/rules/default-case.js

@@ -4,7 +4,7 @@
*/
"use strict";
-const DEFAULT_COMMENT_PATTERN = /^no default$/i;
+const DEFAULT_COMMENT_PATTERN = /^no default$/iu;
//------------------------------------------------------------------------------
// Rule Definition
@@ -39,7 +39,7 @@
create(context) {
const options = context.options[0] || {};
const commentPattern = options.commentPattern
- ? new RegExp(options.commentPattern)
+ ? new RegExp(options.commentPattern) // eslint-disable-line require-unicode-regexp
: DEFAULT_COMMENT_PATTERN;
const sourceCode = context.getSourceCode();

lib/rules/dot-notation.js

@@ -14,7 +14,7 @@
// Rule Definition
//------------------------------------------------------------------------------
-const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
+const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/u;
const keywords = require("../util/keywords");
module.exports = {
@@ -33,10 +33,12 @@
type: "object",
properties: {
allowKeywords: {
- type: "boolean"
+ type: "boolean",
+ default: true
},
allowPattern: {
- type: "string"
+ type: "string",
+ default: ""
}
},
additionalProperties: false
@@ -53,13 +55,13 @@
create(context) {
const options = context.options[0] || {};
- const allowKeywords = options.allowKeywords === void 0 || !!options.allowKeywords;
+ const allowKeywords = options.allowKeywords === void 0 || options.allowKeywords;
const sourceCode = context.getSourceCode();
let allowPattern;
if (options.allowPattern) {
- allowPattern = new RegExp(options.allowPattern);
+ allowPattern = new RegExp(options.allowPattern); // eslint-disable-line require-unicode-regexp
}
/**

lib/rules/eol-last.js

@@ -97,7 +97,7 @@
loc: location,
messageId: "unexpected",
fix(fixer) {
- const finalEOLs = /(?:\r?\n)+$/,
+ const finalEOLs = /(?:\r?\n)+$/u,
match = finalEOLs.exec(sourceCode.text),
start = match.index,
end = sourceCode.text.length;

lib/rules/for-direction.js

@@ -43,6 +43,23 @@
}
/**
+ * check the right side of the assignment
+ * @param {ASTNode} update UpdateExpression to check
+ * @param {int} dir expected direction that could either be turned around or invalidated
+ * @returns {int} return dir, the negated dir or zero if it's not clear for identifiers
+ */
+ function getRightDirection(update, dir) {
+ if (update.right.type === "UnaryExpression") {
+ if (update.right.operator === "-") {
+ return -dir;
+ }
+ } else if (update.right.type === "Identifier") {
+ return 0;
+ }
+ return dir;
+ }
+
+ /**
* check UpdateExpression add/sub the counter
* @param {ASTNode} update UpdateExpression to check
* @param {string} counter variable name to check
@@ -69,10 +86,10 @@
function getAssignmentDirection(update, counter) {
if (update.left.name === counter) {
if (update.operator === "+=") {
- return 1;
+ return getRightDirection(update, 1);
}
if (update.operator === "-=") {
- return -1;
+ return getRightDirection(update, -1);
}
}
return 0;
@@ -85,26 +102,22 @@
const operator = node.test.operator;
const update = node.update;
- if (operator === "<" || operator === "<=") {
+ let wrongDirection;
- // report error if update sub the counter (--, -=)
- if (update.type === "UpdateExpression" && getUpdateDirection(update, counter) < 0) {
- report(node);
- }
-
- if (update.type === "AssignmentExpression" && getAssignmentDirection(update, counter) < 0) {
- report(node);
- }
+ if (operator === "<" || operator === "<=") {
+ wrongDirection = -1;
} else if (operator === ">" || operator === ">=") {
-
- // report error if update add the counter (++, +=)
- if (update.type === "UpdateExpression" && getUpdateDirection(update, counter) > 0) {
- report(node);
+ wrongDirection = 1;
+ } else {
+ return;
}
- if (update.type === "AssignmentExpression" && getAssignmentDirection(update, counter) > 0) {
+ if (update.type === "UpdateExpression") {
+ if (getUpdateDirection(update, counter) === wrongDirection) {
report(node);
}
+ } else if (update.type === "AssignmentExpression" && getAssignmentDirection(update, counter) === wrongDirection) {
+ report(node);
}
}
}

lib/rules/func-call-spacing.js

@@ -92,8 +92,8 @@
return;
}
- const textBetweenTokens = text.slice(prevToken.range[1], parenToken.range[0]).replace(/\/\*.*?\*\//g, "");
- const hasWhitespace = /\s/.test(textBetweenTokens);
+ const textBetweenTokens = text.slice(prevToken.range[1], parenToken.range[0]).replace(/\/\*.*?\*\//gu, "");
+ const hasWhitespace = /\s/u.test(textBetweenTokens);
const hasNewline = hasWhitespace && astUtils.LINEBREAK_MATCHER.test(textBetweenTokens);
/*

lib/rules/func-style.js

@@ -27,7 +27,8 @@
type: "object",
properties: {
allowArrowFunctions: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false
@@ -43,7 +44,7 @@
create(context) {
const style = context.options[0],
- allowArrowFunctions = context.options[1] && context.options[1].allowArrowFunctions === true,
+ allowArrowFunctions = context.options[1] && context.options[1].allowArrowFunctions,
enforceDeclarations = (style === "declaration"),
stack = [];

lib/rules/getter-return.js

@@ -14,7 +14,7 @@
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
-const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/;
+const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/u;
/**
* Checks a given code path segment is reachable.
@@ -60,7 +60,8 @@
type: "object",
properties: {
allowImplicit: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/global-require.js

@@ -57,7 +57,10 @@
url: "https://eslint.org/docs/rules/global-require"
},
- schema: []
+ schema: [],
+ messages: {
+ unexpected: "Unexpected require()."
+ }
},
create(context) {
@@ -69,7 +72,7 @@
const isGoodRequire = context.getAncestors().every(parent => ACCEPTABLE_PARENTS.indexOf(parent.type) > -1);
if (!isGoodRequire) {
- context.report({ node, message: "Unexpected require()." });
+ context.report({ node, messageId: "unexpected" });
}
}
}

lib/rules/guard-for-in.js

@@ -20,7 +20,10 @@
url: "https://eslint.org/docs/rules/guard-for-in"
},
- schema: []
+ schema: [],
+ messages: {
+ wrap: "The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype."
+ }
},
create(context) {
@@ -65,7 +68,7 @@
}
}
- context.report({ node, message: "The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype." });
+ context.report({ node, messageId: "wrap" });
}
};

lib/rules/handle-callback-err.js

@@ -24,7 +24,10 @@
{
type: "string"
}
- ]
+ ],
+ messages: {
+ expected: "Expected error to be handled."
+ }
},
create(context) {
@@ -49,7 +52,7 @@
*/
function matchesConfiguredErrorName(name) {
if (isPattern(errorArgument)) {
- const regexp = new RegExp(errorArgument);
+ const regexp = new RegExp(errorArgument); // eslint-disable-line require-unicode-regexp
return regexp.test(name);
}
@@ -77,7 +80,7 @@
if (firstParameter && matchesConfiguredErrorName(firstParameter.name)) {
if (firstParameter.references.length === 0) {
- context.report({ node, message: "Expected error to be handled." });
+ context.report({ node, messageId: "expected" });
}
}
}

lib/rules/id-blacklist.js

@@ -27,6 +27,9 @@
type: "string"
},
uniqueItems: true
+ },
+ messages: {
+ blacklisted: "Identifier '{{name}}' is blacklisted."
}
},
@@ -72,7 +75,7 @@
function report(node) {
context.report({
node,
- message: "Identifier '{{name}}' is blacklisted.",
+ messageId: "blacklisted",
data: {
name: node.name
}

lib/rules/id-length.js

@@ -26,10 +26,11 @@
type: "object",
properties: {
min: {
- type: "number"
+ type: "integer",
+ default: 2
},
max: {
- type: "number"
+ type: "integer"
},
exceptions: {
type: "array",
@@ -44,7 +45,11 @@
},
additionalProperties: false
}
- ]
+ ],
+ messages: {
+ tooShort: "Identifier name '{{name}}' is too short (< {{min}}).",
+ tooLong: "Identifier name '{{name}}' is too long (> {{max}})."
+ }
},
create(context) {
@@ -107,9 +112,7 @@
if (isValidExpression && (isValidExpression === true || isValidExpression(parent, node))) {
context.report({
node,
- message: isShort
- ? "Identifier name '{{name}}' is too short (< {{min}})."
- : "Identifier name '{{name}}' is too long (> {{max}}).",
+ messageId: isShort ? "tooShort" : "tooLong",
data: { name, min: minLength, max: maxLength }
});
}

lib/rules/id-match.js

@@ -28,17 +28,23 @@
type: "object",
properties: {
properties: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
onlyDeclarations: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
ignoreDestructuring: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
}
}
- ]
+ ],
+ messages: {
+ notMatch: "Identifier '{{name}}' does not match the pattern '{{pattern}}'."
+ }
},
create(context) {
@@ -47,7 +53,7 @@
// Options
//--------------------------------------------------------------------------
const pattern = context.options[0] || "^.+$",
- regexp = new RegExp(pattern);
+ regexp = new RegExp(pattern); // eslint-disable-line require-unicode-regexp
const options = context.options[1] || {},
properties = !!options.properties,
@@ -116,7 +122,7 @@
if (!reported.has(node)) {
context.report({
node,
- message: "Identifier '{{name}}' does not match the pattern '{{pattern}}'.",
+ messageId: "notMatch",
data: {
name: node.name,
pattern

lib/rules/implicit-arrow-linebreak.js

@@ -4,11 +4,7 @@
*/
"use strict";
-const {
- isArrowToken,
- isParenthesised,
- isOpeningParenToken
-} = require("../util/ast-utils");
+const { isCommentToken, isNotOpeningParenToken } = require("../util/ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
@@ -30,158 +26,16 @@
{
enum: ["beside", "below"]
}
- ]
+ ],
+ messages: {
+ expected: "Expected a linebreak before this expression.",
+ unexpected: "Expected no linebreak before this expression."
+ }
},
create(context) {
const sourceCode = context.getSourceCode();
-
- //----------------------------------------------------------------------
- // Helpers
- //----------------------------------------------------------------------
- /**
- * Gets the applicable preference for a particular keyword
- * @returns {string} The applicable option for the keyword, e.g. 'beside'
- */
- function getOption() {
- return context.options[0] || "beside";
- }
-
- /**
- * Formats the comments depending on whether it's a line or block comment.
- * @param {Comment[]} comments The array of comments between the arrow and body
- * @param {Integer} column The column number of the first token
- * @returns {string} A string of comment text joined by line breaks
- */
- function formatComments(comments, column) {
- const whiteSpaces = " ".repeat(column);
-
- return `${comments.map(comment => {
-
- if (comment.type === "Line") {
- return `//${comment.value}`;
- }
-
- return `/*${comment.value}*/`;
- }).join(`\n${whiteSpaces}`)}\n${whiteSpaces}`;
- }
-
- /**
- * Finds the first token to prepend comments to depending on the parent type
- * @param {Node} node The validated node
- * @returns {Token|Node} The node to prepend comments to
- */
- function findFirstToken(node) {
- switch (node.parent.type) {
- case "VariableDeclarator":
-
- // If the parent is first or only declarator, return the declaration, else, declarator
- return sourceCode.getFirstToken(
- node.parent.parent.declarations.length === 1 ||
- node.parent.parent.declarations[0].id.name === node.parent.id.name
- ? node.parent.parent : node.parent
- );
- case "CallExpression":
- case "Property":
-
- // find the object key
- return sourceCode.getFirstToken(node.parent);
- default:
- return node;
- }
- }
-
- /**
- * Helper function for adding parentheses fixes for nodes containing nested arrow functions
- * @param {Fixer} fixer Fixer
- * @param {Token} arrow - The arrow token
- * @param {ASTNode} arrowBody - The arrow function body
- * @returns {Function[]} autofixer -- wraps function bodies with parentheses
- */
- function addParentheses(fixer, arrow, arrowBody) {
- const parenthesesFixes = [];
- let closingParentheses = "";
-
- let followingBody = arrowBody;
- let currentArrow = arrow;
-
- while (currentArrow) {
- if (!isParenthesised(sourceCode, followingBody)) {
- parenthesesFixes.push(
- fixer.insertTextAfter(currentArrow, " (")
- );
-
- const paramsToken = sourceCode.getTokenBefore(currentArrow, token =>
- isOpeningParenToken(token) || token.type === "Identifier");
-
- const whiteSpaces = " ".repeat(paramsToken.loc.start.column);
-
- closingParentheses = `\n${whiteSpaces})${closingParentheses}`;
- }
-
- currentArrow = sourceCode.getTokenAfter(currentArrow, isArrowToken);
-
- if (currentArrow) {
- followingBody = sourceCode.getTokenAfter(currentArrow, token => !isOpeningParenToken(token));
- }
- }
-
- return [...parenthesesFixes,
- fixer.insertTextAfter(arrowBody, closingParentheses)
- ];
- }
-
- /**
- * Autofixes the function body to collapse onto the same line as the arrow.
- * If comments exist, prepends the comments before the arrow function.
- * If the function body contains arrow functions, appends the function bodies with parentheses.
- * @param {Token} arrowToken The arrow token.
- * @param {ASTNode} arrowBody the function body
- * @param {ASTNode} node The evaluated node
- * @returns {Function} autofixer -- validates the node to adhere to besides
- */
- function autoFixBesides(arrowToken, arrowBody, node) {
- return fixer => {
- const placeBesides = fixer.replaceTextRange([arrowToken.range[1], arrowBody.range[0]], " ");
-
- const comments = sourceCode.getCommentsInside(node).filter(comment =>
- comment.loc.start.line < arrowBody.loc.start.line);
-
- if (comments.length) {
-
- // If the grandparent is not a variable declarator
- if (
- arrowBody.parent &&
- arrowBody.parent.parent &&
- arrowBody.parent.parent.type !== "VariableDeclarator"
- ) {
-
- // If any arrow functions follow, return the necessary parens fixes.
- if (sourceCode.getTokenAfter(arrowToken, isArrowToken) && arrowBody.parent.parent.type !== "VariableDeclarator") {
- return addParentheses(fixer, arrowToken, arrowBody);
- }
-
- // If any arrow functions precede, the necessary fixes have already been returned, so return null.
- if (sourceCode.getTokenBefore(arrowToken, isArrowToken) && arrowBody.parent.parent.type !== "VariableDeclarator") {
- return null;
- }
- }
-
- const firstToken = findFirstToken(node);
-
- const commentText = formatComments(comments, firstToken.loc.start.column);
-
- const commentBeforeExpression = fixer.insertTextBeforeRange(
- firstToken.range,
- commentText
- );
-
- return [placeBesides, commentBeforeExpression];
- }
-
- return placeBesides;
- };
- }
+ const option = context.options[0] || "beside";
/**
* Validates the location of an arrow function body
@@ -189,35 +43,30 @@
* @returns {void}
*/
function validateExpression(node) {
- const option = getOption();
-
- let tokenBefore = sourceCode.getTokenBefore(node.body);
- const hasParens = tokenBefore.value === "(";
-
- if (node.type === "BlockStatement") {
+ if (node.body.type === "BlockStatement") {
return;
}
- let fixerTarget = node.body;
+ const arrowToken = sourceCode.getTokenBefore(node.body, isNotOpeningParenToken);
+ const firstTokenOfBody = sourceCode.getTokenAfter(arrowToken);
- if (hasParens) {
-
- // Gets the first token before the function body that is not an open paren
- tokenBefore = sourceCode.getTokenBefore(node.body, token => token.value !== "(");
- fixerTarget = sourceCode.getTokenAfter(tokenBefore);
- }
-
- if (tokenBefore.loc.end.line === fixerTarget.loc.start.line && option === "below") {
+ if (arrowToken.loc.end.line === firstTokenOfBody.loc.start.line && option === "below") {
context.report({
- node: fixerTarget,
- message: "Expected a linebreak before this expression.",
- fix: fixer => fixer.insertTextBefore(fixerTarget, "\n")
+ node: firstTokenOfBody,
+ messageId: "expected",
+ fix: fixer => fixer.insertTextBefore(firstTokenOfBody, "\n")
});
- } else if (tokenBefore.loc.end.line !== fixerTarget.loc.start.line && option === "beside") {
+ } else if (arrowToken.loc.end.line !== firstTokenOfBody.loc.start.line && option === "beside") {
context.report({
- node: fixerTarget,
- message: "Expected no linebreak before this expression.",
- fix: autoFixBesides(tokenBefore, fixerTarget, node)
+ node: firstTokenOfBody,
+ messageId: "unexpected",
+ fix(fixer) {
+ if (sourceCode.getFirstTokenBetween(arrowToken, firstTokenOfBody, { includeComments: true, filter: isCommentToken })) {
+ return null;
+ }
+
+ return fixer.replaceTextRange([arrowToken.range[1], firstTokenOfBody.range[0]], " ");
+ }
});
}
}

lib/rules/indent.js

@@ -442,7 +442,7 @@
const offset = (
offsetInfo.from &&
offsetInfo.from.loc.start.line === token.loc.start.line &&
- !/^\s*?\n/.test(token.value) &&
+ !/^\s*?\n/u.test(token.value) &&
!offsetInfo.force
) ? 0 : offsetInfo.offset * this._indentSize;
@@ -518,7 +518,8 @@
properties: {
SwitchCase: {
type: "integer",
- minimum: 0
+ minimum: 0,
+ default: 0
},
VariableDeclarator: {
oneOf: [
@@ -582,7 +583,8 @@
ObjectExpression: ELEMENT_LIST_SCHEMA,
ImportDeclaration: ELEMENT_LIST_SCHEMA,
flatTernaryExpressions: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
ignoredNodes: {
type: "array",
@@ -594,12 +596,16 @@
}
},
ignoreComments: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false
}
- ]
+ ],
+ messages: {
+ wrongIndentation: "Expected indentation of {{expected}} but found {{actual}}."
+ }
},
create(context) {
@@ -647,7 +653,7 @@
}
if (context.options[1]) {
- lodash.merge(options, context.options[1]);
+ Object.assign(options, context.options[1]);
if (typeof options.VariableDeclarator === "number" || options.VariableDeclarator === "first") {
options.VariableDeclarator = {
@@ -671,7 +677,7 @@
* @param {int} actualTabs The actual number of indentation tabs that were found on this line
* @returns {string} An error message for this line
*/
- function createErrorMessage(expectedAmount, actualSpaces, actualTabs) {
+ function createErrorMessageData(expectedAmount, actualSpaces, actualTabs) {
const expectedStatement = `${expectedAmount} ${indentType}${expectedAmount === 1 ? "" : "s"}`; // e.g. "2 tabs"
const foundSpacesWord = `space${actualSpaces === 1 ? "" : "s"}`; // e.g. "space"
const foundTabsWord = `tab${actualTabs === 1 ? "" : "s"}`; // e.g. "tabs"
@@ -689,8 +695,10 @@
} else {
foundStatement = "0";
}
-
- return `Expected indentation of ${expectedStatement} but found ${foundStatement}.`;
+ return {
+ expected: expectedStatement,
+ actual: foundStatement
+ };
}
/**
@@ -706,7 +714,8 @@
context.report({
node: token,
- message: createErrorMessage(neededIndent.length, numSpaces, numTabs),
+ messageId: "wrongIndentation",
+ data: createErrorMessageData(neededIndent.length, numSpaces, numTabs),
loc: {
start: { line: token.loc.start.line, column: 0 },
end: { line: token.loc.start.line, column: token.loc.start.column }
@@ -776,7 +785,7 @@
* or the total number of linebreaks if the string is all whitespace.
*/
function countTrailingLinebreaks(string) {
- const trailingWhitespace = string.match(/\s*$/)[0];
+ const trailingWhitespace = string.match(/\s*$/u)[0];
const linebreakMatches = trailingWhitespace.match(astUtils.createGlobalLinebreakMatcher());
return linebreakMatches === null ? 0 : linebreakMatches.length;

lib/rules/indent-legacy.js

@@ -169,7 +169,10 @@
},
additionalProperties: false
}
- ]
+ ],
+ messages: {
+ expected: "Expected indentation of {{expected}} but found {{actual}}."
+ }
},
create(context) {
@@ -268,7 +271,7 @@
* @param {int} actualTabs The actual number of indentation tabs that were found on this line
* @returns {string} An error message for this line
*/
- function createErrorMessage(expectedAmount, actualSpaces, actualTabs) {
+ function createErrorMessageData(expectedAmount, actualSpaces, actualTabs) {
const expectedStatement = `${expectedAmount} ${indentType}${expectedAmount === 1 ? "" : "s"}`; // e.g. "2 tabs"
const foundSpacesWord = `space${actualSpaces === 1 ? "" : "s"}`; // e.g. "space"
const foundTabsWord = `tab${actualTabs === 1 ? "" : "s"}`; // e.g. "tabs"
@@ -288,8 +291,10 @@
} else {
foundStatement = "0";
}
-
- return `Expected indentation of ${expectedStatement} but found ${foundStatement}.`;
+ return {
+ expected: expectedStatement,
+ actual: foundStatement
+ };
}
/**
@@ -318,7 +323,8 @@
context.report({
node,
loc,
- message: createErrorMessage(needed, gottenSpaces, gottenTabs),
+ messageId: "expected",
+ data: createErrorMessageData(needed, gottenSpaces, gottenTabs),
fix: fixer => fixer.replaceTextRange(textRange, desiredIndent)
});
}
@@ -969,7 +975,7 @@
* @returns {boolean} the result
*/
function isWrappedInParenthesis(node) {
- const regex = /^return\s*?\(\s*?\);*?/;
+ const regex = /^return\s*?\(\s*?\);*?/u;
const statementWithoutArgument = sourceCode.getText(node).replace(
sourceCode.getText(node.argument), ""

lib/rules/init-declarations.js

@@ -85,6 +85,10 @@
maxItems: 2
}
]
+ },
+ messages: {
+ initialized: "Variable '{{idName}}' should be initialized on declaration.",
+ notInitialized: "Variable '{{idName}}' should not be initialized on declaration."
}
},
@@ -111,23 +115,18 @@
id = declaration.id,
initialized = isInitialized(declaration),
isIgnoredForLoop = params.ignoreForLoopInit && isForLoop(node.parent);
-
- if (id.type !== "Identifier") {
- continue;
- }
+ let messageId = "";
if (mode === MODE_ALWAYS && !initialized) {
- context.report({
- node: declaration,
- message: "Variable '{{idName}}' should be initialized on declaration.",
- data: {
- idName: id.name
- }
- });
+ messageId = "initialized";
} else if (mode === MODE_NEVER && kind !== "const" && initialized && !isIgnoredForLoop) {
+ messageId = "notInitialized";
+ }
+
+ if (id.type === "Identifier" && messageId) {
context.report({
node: declaration,
- message: "Variable '{{idName}}' should not be initialized on declaration.",
+ messageId,
data: {
idName: id.name
}

lib/rules/jsx-quotes.js

@@ -20,14 +20,14 @@
quote: "\"",
description: "singlequote",
convert(str) {
- return str.replace(/'/g, "\"");
+ return str.replace(/'/gu, "\"");
}
},
"prefer-single": {
quote: "'",
description: "doublequote",
convert(str) {
- return str.replace(/"/g, "'");
+ return str.replace(/"/gu, "'");
}
}
};
@@ -53,7 +53,10 @@
{
enum: ["prefer-single", "prefer-double"]
}
- ]
+ ],
+ messages: {
+ unexpected: "Unexpected usage of {{description}}."
+ }
},
create(context) {
@@ -77,7 +80,7 @@
if (attributeValue && astUtils.isStringLiteral(attributeValue) && !usesExpectedQuotes(attributeValue)) {
context.report({
node: attributeValue,
- message: "Unexpected usage of {{description}}.",
+ messageId: "unexpected",
data: {
description: setting.description
},

lib/rules/key-spacing.js

@@ -121,11 +121,6 @@
// Rule Definition
//------------------------------------------------------------------------------
-const messages = {
- key: "{{error}} space after {{computed}}key '{{key}}'.",
- value: "{{error}} space before value for {{computed}}key '{{key}}'."
-};
-
module.exports = {
meta: {
type: "layout",
@@ -297,7 +292,13 @@
additionalProperties: false
}
]
- }]
+ }],
+ messages: {
+ extraKey: "Extra space after {{computed}}key '{{key}}'.",
+ extraValue: "Extra space before value for {{computed}}key '{{key}}'.",
+ missingKey: "Missing space after {{computed}}key '{{key}}'.",
+ missingValue: "Missing space before value for {{computed}}key '{{key}}'."
+ }
},
create(context) {
@@ -460,12 +461,19 @@
}
}
+ let messageId = "";
+
+ if (isExtra) {
+ messageId = side === "key" ? "extraKey" : "extraValue";
+ } else {
+ messageId = side === "key" ? "missingKey" : "missingValue";
+ }
+
context.report({
node: property[side],
loc: locStart,
- message: messages[side],
+ messageId,
data: {
- error: isExtra ? "Extra" : "Missing",
computed: property.computed ? "computed " : "",
key: getKey(property)
},
@@ -493,7 +501,7 @@
* @returns {Object} Whitespace before and after the property's colon.
*/
function getPropertyWhitespace(property) {
- const whitespace = /(\s*):(\s*)/.exec(sourceCode.getText().slice(
+ const whitespace = /(\s*):(\s*)/u.exec(sourceCode.getText().slice(
property.key.range[1], property.value.range[0]
));

lib/rules/keyword-spacing.js

@@ -16,13 +16,13 @@
// Constants
//------------------------------------------------------------------------------
-const PREV_TOKEN = /^[)\]}>]$/;
-const NEXT_TOKEN = /^(?:[([{<~!]|\+\+?|--?)$/;
-const PREV_TOKEN_M = /^[)\]}>*]$/;
-const NEXT_TOKEN_M = /^[{*]$/;
-const TEMPLATE_OPEN_PAREN = /\$\{$/;
-const TEMPLATE_CLOSE_PAREN = /^\}/;
-const CHECK_TYPE = /^(?:JSXElement|RegularExpression|String|Template)$/;
+const PREV_TOKEN = /^[)\]}>]$/u;
+const NEXT_TOKEN = /^(?:[([{<~!]|\+\+?|--?)$/u;
+const PREV_TOKEN_M = /^[)\]}>*]$/u;
+const NEXT_TOKEN_M = /^[{*]$/u;
+const TEMPLATE_OPEN_PAREN = /\$\{$/u;
+const TEMPLATE_CLOSE_PAREN = /^\}/u;
+const CHECK_TYPE = /^(?:JSXElement|RegularExpression|String|Template)$/u;
const KEYS = keywords.concat(["as", "async", "await", "from", "get", "let", "of", "set", "yield"]);
// check duplications.
@@ -80,16 +80,16 @@
{
type: "object",
properties: {
- before: { type: "boolean" },
- after: { type: "boolean" },
+ before: { type: "boolean", default: true },
+ after: { type: "boolean", default: true },
overrides: {
type: "object",
properties: KEYS.reduce((retv, key) => {
retv[key] = {
type: "object",
properties: {
- before: { type: "boolean" },
- after: { type: "boolean" }
+ before: { type: "boolean", default: true },
+ after: { type: "boolean", default: true }
},
additionalProperties: false
};
@@ -100,7 +100,13 @@
},
additionalProperties: false
}
- ]
+ ],
+ messages: {
+ expectedBefore: "Expected space(s) before \"{{value}}\".",
+ expectedAfter: "Expected space(s) after \"{{value}}\".",
+ unexpectedBefore: "Unexpected space(s) before \"{{value}}\".",
+ unexpectedAfter: "Unexpected space(s) after \"{{value}}\"."
+ }
},
create(context) {
@@ -124,7 +130,7 @@
) {
context.report({
loc: token.loc.start,
- message: "Expected space(s) before \"{{value}}\".",
+ messageId: "expectedBefore",
data: token,
fix(fixer) {
return fixer.insertTextBefore(token, " ");
@@ -151,7 +157,7 @@
) {
context.report({
loc: token.loc.start,
- message: "Unexpected space(s) before \"{{value}}\".",
+ messageId: "unexpectedBefore",
data: token,
fix(fixer) {
return fixer.removeRange([prevToken.range[1], token.range[0]]);
@@ -178,7 +184,7 @@
) {
context.report({
loc: token.loc.start,
- message: "Expected space(s) after \"{{value}}\".",
+ messageId: "expectedAfter",
data: token,
fix(fixer) {
return fixer.insertTextAfter(token, " ");
@@ -205,7 +211,7 @@
) {
context.report({
loc: token.loc.start,
- message: "Unexpected space(s) after \"{{value}}\".",
+ messageId: "unexpectedAfter",
data: token,
fix(fixer) {
return fixer.removeRange([token.range[1], nextToken.range[0]]);
@@ -222,9 +228,9 @@
* Keys are keywords (there are for every keyword).
* Values are instances of `{"before": function, "after": function}`.
*/
- function parseOptions(options) {
- const before = !options || options.before !== false;
- const after = !options || options.after !== false;
+ function parseOptions(options = {}) {
+ const before = options.before !== false;
+ const after = options.after !== false;
const defaultValue = {
before: before ? expectSpaceBefore : unexpectSpaceBefore,
after: after ? expectSpaceAfter : unexpectSpaceAfter

lib/rules/linebreak-style.js

@@ -32,14 +32,14 @@
{
enum: ["unix", "windows"]
}
- ]
+ ],
+ messages: {
+ expectedLF: "Expected linebreaks to be 'LF' but found 'CRLF'.",
+ expectedCRLF: "Expected linebreaks to be 'CRLF' but found 'LF'."
+ }
},
create(context) {
-
- const EXPECTED_LF_MSG = "Expected linebreaks to be 'LF' but found 'CRLF'.",
- EXPECTED_CRLF_MSG = "Expected linebreaks to be 'CRLF' but found 'LF'.";
-
const sourceCode = context.getSourceCode();
//--------------------------------------------------------------------------
@@ -89,7 +89,7 @@
line: i,
column: sourceCode.lines[i - 1].length
},
- message: expectedLF ? EXPECTED_LF_MSG : EXPECTED_CRLF_MSG,
+ messageId: expectedLF ? "expectedLF" : "expectedCRLF",
fix: createFix(range, expectedLFChars)
});
}

lib/rules/line-comment-position.js

@@ -31,7 +31,8 @@
type: "object",
properties: {
position: {
- enum: ["above", "beside"]
+ enum: ["above", "beside"],
+ default: "above"
},
ignorePattern: {
type: "string"
@@ -47,7 +48,11 @@
}
]
}
- ]
+ ],
+ messages: {
+ above: "Expected comment to be above code.",
+ beside: "Expected comment to be beside code."
+ }
},
create(context) {
@@ -65,15 +70,15 @@
ignorePattern = options.ignorePattern;
if (Object.prototype.hasOwnProperty.call(options, "applyDefaultIgnorePatterns")) {
- applyDefaultIgnorePatterns = options.applyDefaultIgnorePatterns !== false;
+ applyDefaultIgnorePatterns = options.applyDefaultIgnorePatterns;
} else {
applyDefaultIgnorePatterns = options.applyDefaultPatterns !== false;
}
}
const defaultIgnoreRegExp = astUtils.COMMENTS_IGNORE_PATTERN;
- const fallThroughRegExp = /^\s*falls?\s?through/;
- const customIgnoreRegExp = new RegExp(ignorePattern);
+ const fallThroughRegExp = /^\s*falls?\s?through/u;
+ const customIgnoreRegExp = new RegExp(ignorePattern); // eslint-disable-line require-unicode-regexp
const sourceCode = context.getSourceCode();
//--------------------------------------------------------------------------
@@ -100,14 +105,14 @@
if (isOnSameLine) {
context.report({
node,
- message: "Expected comment to be above code."
+ messageId: "above"
});
}
} else {
if (!isOnSameLine) {
context.report({
node,
- message: "Expected comment to be beside code."
+ messageId: "beside"
});
}
}

lib/rules/lines-around-comment.js

@@ -68,22 +68,28 @@
type: "object",
properties: {
beforeBlockComment: {
- type: "boolean"
+ type: "boolean",
+ default: true
},
afterBlockComment: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
beforeLineComment: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
afterLineComment: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
allowBlockStart: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
allowBlockEnd: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
allowClassStart: {
type: "boolean"
@@ -112,24 +118,22 @@
},
additionalProperties: false
}
- ]
+ ],
+ messages: {
+ after: "Expected line after comment.",
+ before: "Expected line before comment."
+ }
},
create(context) {
- const options = context.options[0] ? Object.assign({}, context.options[0]) : {};
+ const options = Object.assign({}, context.options[0]);
const ignorePattern = options.ignorePattern;
const defaultIgnoreRegExp = astUtils.COMMENTS_IGNORE_PATTERN;
- const customIgnoreRegExp = new RegExp(ignorePattern);
+ const customIgnoreRegExp = new RegExp(ignorePattern); // eslint-disable-line require-unicode-regexp
const applyDefaultIgnorePatterns = options.applyDefaultIgnorePatterns !== false;
-
- options.beforeLineComment = options.beforeLineComment || false;
- options.afterLineComment = options.afterLineComment || false;
options.beforeBlockComment = typeof options.beforeBlockComment !== "undefined" ? options.beforeBlockComment : true;
- options.afterBlockComment = options.afterBlockComment || false;
- options.allowBlockStart = options.allowBlockStart || false;
- options.allowBlockEnd = options.allowBlockEnd || false;
const sourceCode = context.getSourceCode();
@@ -350,7 +354,7 @@
context.report({
node: token,
- message: "Expected line before comment.",
+ messageId: "before",
fix(fixer) {
return fixer.insertTextBeforeRange(range, "\n");
}
@@ -362,7 +366,7 @@
!(astUtils.isCommentToken(nextTokenOrComment) && astUtils.isTokenOnSameLine(token, nextTokenOrComment))) {
context.report({
node: token,
- message: "Expected line after comment.",
+ messageId: "after",
fix(fixer) {
return fixer.insertTextAfter(token, "\n");
}

lib/rules/lines-around-directive.js

@@ -45,6 +45,10 @@
}],
fixable: "whitespace",
+ messages: {
+ expected: "Expected newline {{location}} \"{{value}}\" directive.",
+ unexpected: "Unexpected newline {{location}} \"{{value}}\" directive."
+ },
deprecated: true,
replacedBy: ["padding-line-between-statements"]
},
@@ -109,9 +113,8 @@
function reportError(node, location, expected) {
context.report({
node,
- message: "{{expected}} newline {{location}} \"{{value}}\" directive.",
+ messageId: expected ? "expected" : "unexpected",
data: {
- expected: expected ? "Expected" : "Unexpected",
value: node.expression.value,
location
},

lib/rules/lines-between-class-members.js

@@ -31,12 +31,17 @@
type: "object",
properties: {
exceptAfterSingleLine: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false
}
- ]
+ ],
+ messages: {
+ never: "Unexpected blank line between class members.",
+ always: "Expected blank line between class members."
+ }
},
create(context) {
@@ -46,9 +51,6 @@
options[0] = context.options[0] || "always";
options[1] = context.options[1] || { exceptAfterSingleLine: false };
- const ALWAYS_MESSAGE = "Expected blank line between class members.";
- const NEVER_MESSAGE = "Unexpected blank line between class members.";
-
const sourceCode = context.getSourceCode();
/**
@@ -127,7 +129,7 @@
(options[0] === "never" && isPadded)) {
context.report({
node: body[i + 1],
- message: isPadded ? NEVER_MESSAGE : ALWAYS_MESSAGE,
+ messageId: isPadded ? "never" : "always",
fix(fixer) {
return isPadded
? fixer.replaceTextRange([curLast.range[1], nextFirst.range[0]], "\n")

lib/rules/max-depth.js

@@ -43,7 +43,10 @@
}
]
}
- ]
+ ],
+ messages: {
+ tooDeeply: "Blocks are nested too deeply ({{depth}})."
+ }
},
create(context) {
@@ -56,11 +59,11 @@
option = context.options[0];
let maxDepth = 4;
- if (typeof option === "object" && Object.prototype.hasOwnProperty.call(option, "maximum") && typeof option.maximum === "number") {
- maxDepth = option.maximum;
- }
- if (typeof option === "object" && Object.prototype.hasOwnProperty.call(option, "max") && typeof option.max === "number") {
- maxDepth = option.max;
+ if (
+ typeof option === "object" &&
+ (Object.prototype.hasOwnProperty.call(option, "maximum") || Object.prototype.hasOwnProperty.call(option, "max"))
+ ) {
+ maxDepth = option.maximum || option.max;
}
if (typeof option === "number") {
maxDepth = option;
@@ -94,7 +97,7 @@
const len = ++functionStack[functionStack.length - 1];
if (len > maxDepth) {
- context.report({ node, message: "Blocks are nested too deeply ({{depth}}).", data: { depth: len } });
+ context.report({ node, messageId: "tooDeeply", data: { depth: len } });
}
}

lib/rules/max-len.js

@@ -14,7 +14,8 @@
properties: {
code: {
type: "integer",
- minimum: 0
+ minimum: 0,
+ default: 80
},
comments: {
type: "integer",
@@ -22,28 +23,35 @@
},
tabWidth: {
type: "integer",
- minimum: 0
+ minimum: 0,
+ default: 4
},
ignorePattern: {
type: "string"
},
ignoreComments: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
ignoreStrings: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
ignoreUrls: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
ignoreTemplateLiterals: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
ignoreRegExpLiterals: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
ignoreTrailingComments: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false
@@ -78,7 +86,11 @@
OPTIONS_OR_INTEGER_SCHEMA,
OPTIONS_OR_INTEGER_SCHEMA,
OPTIONS_SCHEMA
- ]
+ ],
+ messages: {
+ max: "Line {{lineNumber}} exceeds the maximum line length of {{maxLength}}.",
+ maxComment: "Line {{lineNumber}} exceeds the maximum comment line length of {{maxCommentLength}}."
+ }
},
create(context) {
@@ -91,7 +103,7 @@
* too many false positives
* - We don't care about matching the entire URL, any small segment is fine
*/
- const URL_REGEXP = /[^:/?#]:\/\/[^?#]/;
+ const URL_REGEXP = /[^:/?#]:\/\/[^?#]/u;
const sourceCode = context.getSourceCode();
@@ -106,7 +118,7 @@
function computeLineLength(line, tabWidth) {
let extraCharacterCount = 0;
- line.replace(/\t/g, (match, offset) => {
+ line.replace(/\t/gu, (match, offset) => {
const totalOffset = offset + extraCharacterCount,
previousTabStopOffset = tabWidth ? totalOffset % tabWidth : 0,
spaceCount = tabWidth - previousTabStopOffset;
@@ -117,8 +129,7 @@
}
// The options object must be the last option specified…
- const lastOption = context.options[context.options.length - 1];
- const options = typeof lastOption === "object" ? Object.create(lastOption) : {};
+ const options = Object.assign({}, context.options[context.options.length - 1]);
// …but max code length…
if (typeof context.options[0] === "number") {
@@ -142,7 +153,7 @@
let ignorePattern = options.ignorePattern || null;
if (ignorePattern) {
- ignorePattern = new RegExp(ignorePattern);
+ ignorePattern = new RegExp(ignorePattern); // eslint-disable-line require-unicode-regexp
}
//--------------------------------------------------------------------------
@@ -190,7 +201,7 @@
function stripTrailingComment(line, comment) {
// loc.column is zero-indexed
- return line.slice(0, comment.loc.start.column).replace(/\s+$/, "");
+ return line.slice(0, comment.loc.start.column).replace(/\s+$/u, "");
}
/**
@@ -341,7 +352,7 @@
context.report({
node,
loc: { line: lineNumber, column: 0 },
- message: "Line {{lineNumber}} exceeds the maximum comment line length of {{maxCommentLength}}.",
+ messageId: "maxComment",
data: {
lineNumber: i + 1,
maxCommentLength
@@ -352,7 +363,7 @@
context.report({
node,
loc: { line: lineNumber, column: 0 },
- message: "Line {{lineNumber}} exceeds the maximum line length of {{maxLength}}.",
+ messageId: "max",
data: {
lineNumber: i + 1,
maxLength

lib/rules/max-lines.js

@@ -51,18 +51,19 @@
}
]
}
- ]
+ ],
+ messages: {
+ exceed: "File must be at most {{max}} lines long. It's {{actual}} lines long."
+ }
},
create(context) {
const option = context.options[0];
let max = 300;
- if (typeof option === "object" && Object.prototype.hasOwnProperty.call(option, "max") && typeof option.max === "number") {
+ if (typeof option === "object" && Object.prototype.hasOwnProperty.call(option, "max")) {
max = option.max;
- }
-
- if (typeof option === "number") {
+ } else if (typeof option === "number") {
max = option;
}
@@ -83,7 +84,7 @@
/**
* Returns the line numbers of a comment that don't have any code on the same line
* @param {Node} comment The comment node to check
- * @returns {int[]} The line numbers
+ * @returns {number[]} The line numbers
*/
function getLinesWithoutCode(comment) {
let start = comment.loc.start.line;
@@ -134,7 +135,7 @@
if (lines.length > max) {
context.report({
loc: { line: 1, column: 0 },
- message: "File must be at most {{max}} lines long. It's {{actual}} lines long.",
+ messageId: "exceed",
data: {
max,
actual: lines.length

lib/rules/max-lines-per-function.js

@@ -19,16 +19,20 @@
properties: {
max: {
type: "integer",
- minimum: 0
+ minimum: 0,
+ default: 50
},
skipComments: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
skipBlankLines: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
IIFEs: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false
@@ -80,7 +84,10 @@
schema: [
OPTIONS_OR_INTEGER_SCHEMA
- ]
+ ],
+ messages: {
+ exceed: "{{name}} has too many lines ({{lineCount}}). Maximum allowed is {{maxLines}}."
+ }
},
create(context) {
@@ -94,18 +101,10 @@
let IIFEs = false;
if (typeof option === "object") {
- if (typeof option.max === "number") {
maxLines = option.max;
- }
- if (typeof option.skipComments === "boolean") {
skipComments = option.skipComments;
- }
- if (typeof option.skipBlankLines === "boolean") {
skipBlankLines = option.skipBlankLines;
- }
- if (typeof option.IIFEs === "boolean") {
IIFEs = option.IIFEs;
- }
} else if (typeof option === "number") {
maxLines = option;
}
@@ -188,7 +187,7 @@
}
if (skipBlankLines) {
- if (line.match(/^\s*$/)) {
+ if (line.match(/^\s*$/u)) {
continue;
}
}
@@ -201,7 +200,7 @@
context.report({
node,
- message: "{{name}} has too many lines ({{lineCount}}). Maximum allowed is {{maxLines}}.",
+ messageId: "exceed",
data: { name, lineCount, maxLines }
});
}

lib/rules/max-nested-callbacks.js

@@ -43,7 +43,10 @@
}
]
}
- ]
+ ],
+ messages: {
+ exceed: "Too many nested callbacks ({{num}}). Maximum allowed is {{max}}."
+ }
},
create(context) {
@@ -54,13 +57,12 @@
const option = context.options[0];
let THRESHOLD = 10;
- if (typeof option === "object" && Object.prototype.hasOwnProperty.call(option, "maximum") && typeof option.maximum === "number") {
- THRESHOLD = option.maximum;
- }
- if (typeof option === "object" && Object.prototype.hasOwnProperty.call(option, "max") && typeof option.max === "number") {
- THRESHOLD = option.max;
- }
- if (typeof option === "number") {
+ if (
+ typeof option === "object" &&
+ (Object.prototype.hasOwnProperty.call(option, "maximum") || Object.prototype.hasOwnProperty.call(option, "max"))
+ ) {
+ THRESHOLD = option.maximum || option.max;
+ } else if (typeof option === "number") {
THRESHOLD = option;
}
@@ -86,7 +88,7 @@
if (callbackStack.length > THRESHOLD) {
const opts = { num: callbackStack.length, max: THRESHOLD };
- context.report({ node, message: "Too many nested callbacks ({{num}}). Maximum allowed is {{max}}.", data: opts });
+ context.report({ node, messageId: "exceed", data: opts });
}
}

lib/rules/max-params.js

@@ -51,7 +51,10 @@
}
]
}
- ]
+ ],
+ messages: {
+ exceed: "{{name}} has too many parameters ({{count}}). Maximum allowed is {{max}}."
+ }
},
create(context) {
@@ -59,11 +62,11 @@
const option = context.options[0];
let numParams = 3;
- if (typeof option === "object" && Object.prototype.hasOwnProperty.call(option, "maximum") && typeof option.maximum === "number") {
- numParams = option.maximum;
- }
- if (typeof option === "object" && Object.prototype.hasOwnProperty.call(option, "max") && typeof option.max === "number") {
- numParams = option.max;
+ if (
+ typeof option === "object" &&
+ (Object.prototype.hasOwnProperty.call(option, "maximum") || Object.prototype.hasOwnProperty.call(option, "max"))
+ ) {
+ numParams = option.maximum || option.max;
}
if (typeof option === "number") {
numParams = option;
@@ -80,7 +83,7 @@
context.report({
loc: astUtils.getFunctionHeadLoc(node, sourceCode),
node,
- message: "{{name}} has too many parameters ({{count}}). Maximum allowed is {{max}}.",
+ messageId: "exceed",
data: {
name: lodash.upperFirst(astUtils.getFunctionNameWithKind(node)),
count: node.params.length,

lib/rules/max-statements.js

@@ -60,7 +60,10 @@
},
additionalProperties: false
}
- ]
+ ],
+ messages: {
+ exceed: "{{name}} has too many statements ({{count}}). Maximum allowed is {{max}}."
+ }
},
create(context) {
@@ -75,13 +78,12 @@
topLevelFunctions = [];
let maxStatements = 10;
- if (typeof option === "object" && Object.prototype.hasOwnProperty.call(option, "maximum") && typeof option.maximum === "number") {
- maxStatements = option.maximum;
- }
- if (typeof option === "object" && Object.prototype.hasOwnProperty.call(option, "max") && typeof option.max === "number") {
- maxStatements = option.max;
- }
- if (typeof option === "number") {
+ if (
+ typeof option === "object" &&
+ (Object.prototype.hasOwnProperty.call(option, "maximum") || Object.prototype.hasOwnProperty.call(option, "max"))
+ ) {
+ maxStatements = option.maximum || option.max;
+ } else if (typeof option === "number") {
maxStatements = option;
}
@@ -99,7 +101,7 @@
context.report({
node,
- message: "{{name}} has too many statements ({{count}}). Maximum allowed is {{max}}.",
+ messageId: "exceed",
data: { name, count, max }
});
}

lib/rules/max-statements-per-line.js

@@ -31,20 +31,23 @@
properties: {
max: {
type: "integer",
- minimum: 1
+ minimum: 1,
+ default: 1
}
},
additionalProperties: false
}
- ]
+ ],
+ messages: {
+ exceed: "This line has {{numberOfStatementsOnThisLine}} {{statements}}. Maximum allowed is {{maxStatementsPerLine}}."
+ }
},
create(context) {
const sourceCode = context.getSourceCode(),
options = context.options[0] || {},
- maxStatementsPerLine = typeof options.max !== "undefined" ? options.max : 1,
- message = "This line has {{numberOfStatementsOnThisLine}} {{statements}}. Maximum allowed is {{maxStatementsPerLine}}.";
+ maxStatementsPerLine = typeof options.max !== "undefined" ? options.max : 1;
let lastStatementLine = 0,
numberOfStatementsOnThisLine = 0,
@@ -54,7 +57,7 @@
// Helpers
//--------------------------------------------------------------------------
- const SINGLE_CHILD_ALLOWED = /^(?:(?:DoWhile|For|ForIn|ForOf|If|Labeled|While)Statement|Export(?:Default|Named)Declaration)$/;
+ const SINGLE_CHILD_ALLOWED = /^(?:(?:DoWhile|For|ForIn|ForOf|If|Labeled|While)Statement|Export(?:Default|Named)Declaration)$/u;
/**
* Reports with the first extra statement, and clears it.
@@ -65,7 +68,7 @@
if (firstExtraStatement) {
context.report({
node: firstExtraStatement,
- message,
+ messageId: "exceed",
data: {
numberOfStatementsOnThisLine,
maxStatementsPerLine,

lib/rules/multiline-comment-style.js

@@ -22,20 +22,21 @@
},
fixable: "whitespace",
- schema: [{ enum: ["starred-block", "separate-lines", "bare-block"] }]
+ schema: [{ enum: ["starred-block", "separate-lines", "bare-block"] }],
+ messages: {
+ expectedBlock: "Expected a block comment instead of consecutive line comments.",
+ startNewline: "Expected a linebreak after '/*'.",
+ endNewline: "Expected a linebreak before '*/'.",
+ missingStar: "Expected a '*' at the start of this line.",
+ alignment: "Expected this line to be aligned with the start of the comment.",
+ expectedLines: "Expected multiple line comments instead of a block comment."
+ }
},
create(context) {
const sourceCode = context.getSourceCode();
const option = context.options[0] || "starred-block";
- const EXPECTED_BLOCK_ERROR = "Expected a block comment instead of consecutive line comments.";
- const START_NEWLINE_ERROR = "Expected a linebreak after '/*'.";
- const END_NEWLINE_ERROR = "Expected a linebreak before '*/'.";
- const MISSING_STAR_ERROR = "Expected a '*' at the start of this line.";
- const ALIGNMENT_ERROR = "Expected this line to be aligned with the start of the comment.";
- const EXPECTED_LINES_ERROR = "Expected multiple line comments instead of a block comment.";
-
//----------------------------------------------------------------------
// Helpers
//----------------------------------------------------------------------
@@ -51,7 +52,7 @@
}
return commentGroup[0].value
.split(astUtils.LINEBREAK_MATCHER)
- .map(line => line.replace(/^\s*\*?/, ""));
+ .map(line => line.replace(/^\s*\*?/u, ""));
}
/**
@@ -102,9 +103,9 @@
const lines = commentGroup[0].value.split(astUtils.LINEBREAK_MATCHER);
return commentGroup[0].type === "Block" &&
- /^\*\s*$/.test(lines[0]) &&
- lines.slice(1, -1).every(line => /^\s* /.test(line)) &&
- /^\s*$/.test(lines[lines.length - 1]);
+ /^\*\s*$/u.test(lines[0]) &&
+ lines.slice(1, -1).every(line => /^\s* /u.test(line)) &&
+ /^\s*$/u.test(lines[lines.length - 1]);
}
/**
@@ -127,7 +128,7 @@
start: commentGroup[0].loc.start,
end: commentGroup[commentGroup.length - 1].loc.end
},
- message: EXPECTED_BLOCK_ERROR,
+ messageId: "expectedBlock",
fix(fixer) {
const range = [commentGroup[0].range[0], commentGroup[commentGroup.length - 1].range[1]];
const starredBlock = `/*${convertToStarredBlock(commentGroup[0], commentLines)}*/`;
@@ -142,7 +143,7 @@
const lines = block.value.split(astUtils.LINEBREAK_MATCHER);
const expectedLinePrefix = `${sourceCode.text.slice(block.range[0] - block.loc.start.column, block.range[0])} *`;
- if (!/^\*?\s*$/.test(lines[0])) {
+ if (!/^\*?\s*$/u.test(lines[0])) {
const start = block.value.startsWith("*") ? block.range[0] + 1 : block.range[0];
context.report({
@@ -150,18 +151,18 @@
start: block.loc.start,
end: { line: block.loc.start.line, column: block.loc.start.column + 2 }
},
- message: START_NEWLINE_ERROR,
+ messageId: "startNewline",
fix: fixer => fixer.insertTextAfterRange([start, start + 2], `\n${expectedLinePrefix}`)
});
}
- if (!/^\s*$/.test(lines[lines.length - 1])) {
+ if (!/^\s*$/u.test(lines[lines.length - 1])) {
context.report({
loc: {
start: { line: block.loc.end.line, column: block.loc.end.column - 2 },
end: block.loc.end
},
- message: END_NEWLINE_ERROR,
+ messageId: "endNewline",
fix: fixer => fixer.replaceTextRange([block.range[1] - 2, block.range[1]], `\n${expectedLinePrefix}/`)
});
}
@@ -175,12 +176,12 @@
start: { line: lineNumber, column: 0 },
end: { line: lineNumber, column: sourceCode.lines[lineNumber - 1].length }
},
- message: /^\s*\*/.test(lineText)
- ? ALIGNMENT_ERROR
- : MISSING_STAR_ERROR,
+ messageId: /^\s*\*/u.test(lineText)
+ ? "alignment"
+ : "missingStar",
fix(fixer) {
const lineStartIndex = sourceCode.getIndexFromLoc({ line: lineNumber, column: 0 });
- const linePrefixLength = lineText.match(/^\s*\*? ?/)[0].length;
+ const linePrefixLength = lineText.match(/^\s*\*? ?/u)[0].length;
const commentStartIndex = lineStartIndex + linePrefixLength;
const replacementText = lineNumber === block.loc.end.line || lineText.length === linePrefixLength
@@ -209,7 +210,7 @@
start: block.loc.start,
end: { line: block.loc.start.line, column: block.loc.start.column + 2 }
},
- message: EXPECTED_LINES_ERROR,
+ messageId: "expectedLines",
fix(fixer) {
return fixer.replaceText(block, convertToSeparateLines(block, commentLines.filter(line => line)));
}
@@ -228,7 +229,7 @@
start: commentGroup[0].loc.start,
end: commentGroup[commentGroup.length - 1].loc.end
},
- message: EXPECTED_BLOCK_ERROR,
+ messageId: "expectedBlock",
fix(fixer) {
const range = [commentGroup[0].range[0], commentGroup[commentGroup.length - 1].range[1]];
const block = convertToBlock(commentGroup[0], commentLines.filter(line => line));
@@ -243,13 +244,13 @@
const block = commentGroup[0];
const lines = block.value.split(astUtils.LINEBREAK_MATCHER).filter(line => line.trim());
- if (lines.length > 0 && lines.every(line => /^\s*\*/.test(line))) {
+ if (lines.length > 0 && lines.every(line => /^\s*\*/u.test(line))) {
context.report({
loc: {
start: block.loc.start,
end: { line: block.loc.start.line, column: block.loc.start.column + 2 }
},
- message: EXPECTED_BLOCK_ERROR,
+ messageId: "expectedBlock",
fix(fixer) {
return fixer.replaceText(block, convertToBlock(block, commentLines.filter(line => line)));
}

lib/rules/multiline-ternary.js

@@ -26,7 +26,13 @@
{
enum: ["always", "always-multiline", "never"]
}
- ]
+ ],
+ messages: {
+ expectedTestCons: "Expected newline between test and consequent of ternary expression.",
+ expectedConsAlt: "Expected newline between consequent and alternate of ternary expression.",
+ unexpectedTestCons: "Unexpected newline between test and consequent of ternary expression.",
+ unexpectedConsAlt: "Unexpected newline between consequent and alternate of ternary expression."
+ }
},
create(context) {
@@ -49,11 +55,7 @@
function reportError(node, parentNode, expected) {
context.report({
node,
- message: "{{expected}} newline between {{typeOfError}} of ternary expression.",
- data: {
- expected: expected ? "Expected" : "Unexpected",
- typeOfError: node === parentNode.test ? "test and consequent" : "consequent and alternate"
- }
+ messageId: `${expected ? "expected" : "unexpected"}${node === parentNode.test ? "TestCons" : "ConsAlt"}`
});
}

lib/rules/new-cap.js

@@ -88,10 +88,12 @@
type: "object",
properties: {
newIsCap: {
- type: "boolean"
+ type: "boolean",
+ default: true
},
capIsNew: {
- type: "boolean"
+ type: "boolean",
+ default: true
},
newIsCapExceptions: {
type: "array",
@@ -112,27 +114,32 @@
type: "string"
},
properties: {
- type: "boolean"
+ type: "boolean",
+ default: true
}
},
additionalProperties: false
}
- ]
+ ],
+ messages: {
+ upper: "A function with a name starting with an uppercase letter should only be used as a constructor.",
+ lower: "A constructor name should not start with a lowercase letter."
+ }
},
create(context) {
- const config = context.options[0] ? Object.assign({}, context.options[0]) : {};
+ const config = Object.assign({}, context.options[0]);
config.newIsCap = config.newIsCap !== false;
config.capIsNew = config.capIsNew !== false;
const skipProperties = config.properties === false;
const newIsCapExceptions = checkArray(config, "newIsCapExceptions", []).reduce(invert, {});
- const newIsCapExceptionPattern = config.newIsCapExceptionPattern ? new RegExp(config.newIsCapExceptionPattern) : null;
+ const newIsCapExceptionPattern = config.newIsCapExceptionPattern ? new RegExp(config.newIsCapExceptionPattern) : null; // eslint-disable-line require-unicode-regexp
const capIsNewExceptions = calculateCapIsNewExceptions(config);
- const capIsNewExceptionPattern = config.capIsNewExceptionPattern ? new RegExp(config.capIsNewExceptionPattern) : null;
+ const capIsNewExceptionPattern = config.capIsNewExceptionPattern ? new RegExp(config.capIsNewExceptionPattern) : null; // eslint-disable-line require-unicode-regexp
const listeners = {};
@@ -219,19 +226,19 @@
}
/**
- * Reports the given message for the given node. The location will be the start of the property or the callee.
+ * Reports the given messageId for the given node. The location will be the start of the property or the callee.
* @param {ASTNode} node CallExpression or NewExpression node.
- * @param {string} message The message to report.
+ * @param {string} messageId The messageId to report.
* @returns {void}
*/
- function report(node, message) {
+ function report(node, messageId) {
let callee = node.callee;
if (callee.type === "MemberExpression") {
callee = callee.property;
}
- context.report({ node, loc: callee.loc.start, message });
+ context.report({ node, loc: callee.loc.start, messageId });
}
//--------------------------------------------------------------------------
@@ -248,7 +255,7 @@
const isAllowed = capitalization !== "lower" || isCapAllowed(newIsCapExceptions, node, constructorName, newIsCapExceptionPattern);
if (!isAllowed) {
- report(node, "A constructor name should not start with a lowercase letter.");
+ report(node, "lower");
}
}
};
@@ -264,7 +271,7 @@
const isAllowed = capitalization !== "upper" || isCapAllowed(capIsNewExceptions, node, calleeName, capIsNewExceptionPattern);
if (!isAllowed) {
- report(node, "A function with a name starting with an uppercase letter should only be used as a constructor.");
+ report(node, "upper");
}
}
};

lib/rules/newline-after-var.js

@@ -32,8 +31,11 @@
enum: ["never", "always"]
}
],
-
fixable: "whitespace",
+ messages: {
+ expected: "Expected blank line after variable declarations.",
+ unexpected: "Unexpected blank line after variable declarations."
+ },
deprecated: true,
@@ -41,10 +43,6 @@
},
create(context) {
-
- const ALWAYS_MESSAGE = "Expected blank line after variable declarations.",
- NEVER_MESSAGE = "Unexpected blank line after variable declarations.";
-
const sourceCode = context.getSourceCode();
// Default `mode` to "always".
@@ -214,7 +212,7 @@
if (mode === "never" && noNextLineToken && !hasNextLineComment) {
context.report({
node,
- message: NEVER_MESSAGE,
+ messageId: "unexpected",
data: { identifier: node.name },
fix(fixer) {
const linesBetween = sourceCode.getText().slice(lastToken.range[1], nextToken.range[0]).split(astUtils.LINEBREAK_MATCHER);
@@ -233,7 +231,7 @@
) {
context.report({
node,
- message: ALWAYS_MESSAGE,
+ messageId: "expected",
data: { identifier: node.name },
fix(fixer) {
if ((noNextLineToken ? getLastCommentLineOfBlock(nextLineNum) : lastToken.loc.end.line) === nextToken.loc.start.line) {

lib/rules/newline-before-return.js

@@ -22,6 +22,10 @@
fixable: "whitespace",
schema: [],
+ messages: {
+ expected: "Expected newline before return statement."
+ },
+
deprecated: true,
replacedBy: ["padding-line-between-statements"]
},
@@ -196,7 +200,7 @@
if (!isFirstNode(node) && !hasNewlineBefore(node)) {
context.report({
node,
- message: "Expected newline before return statement.",
+ messageId: "expected",
fix(fixer) {
if (canFix(node)) {
const tokenBefore = sourceCode.getTokenBefore(node);

lib/rules/newline-per-chained-call.js

@@ -31,11 +31,15 @@
ignoreChainWithDepth: {
type: "integer",
minimum: 1,
- maximum: 10
+ maximum: 10,
+ default: 2
}
},
additionalProperties: false
- }]
+ }],
+ messages: {
+ expected: "Expected line break before `{{callee}}`."
+ }
},
create(context) {
@@ -91,7 +95,7 @@
context.report({
node: callee.property,
loc: callee.property.loc.start,
- message: "Expected line break before `{{callee}}`.",
+ messageId: "expected",
data: {
callee: getPropertyText(callee)
},

lib/rules/new-parens.js

@@ -30,8 +30,11 @@
url: "https://eslint.org/docs/rules/new-parens"
},
+ fixable: "code",
schema: [],
- fixable: "code"
+ messages: {
+ missing: "Missing '()' invoking a constructor."
+ }
},
create(context) {
@@ -50,7 +53,7 @@
if (!hasParens) {
context.report({
node,
- message: "Missing '()' invoking a constructor.",
+ messageId: "missing",
fix: fixer => fixer.insertTextAfter(node, "()")
});
}

lib/rules/no-alert.js

@@ -20,7 +20,7 @@
* @returns {boolean} Whether or not the name is prohibited.
*/
function isProhibitedIdentifier(name) {
- return /^(alert|confirm|prompt)$/.test(name);
+ return /^(alert|confirm|prompt)$/u.test(name);
}
/**

lib/rules/no-async-promise-executor.js

@@ -20,7 +20,10 @@
},
fixable: null,
- schema: []
+ schema: [],
+ messages: {
+ async: "Promise executor functions should not be async."
+ }
},
create(context) {
@@ -28,7 +31,7 @@
"NewExpression[callee.name='Promise'][arguments.0.async=true]"(node) {
context.report({
node: context.getSourceCode().getFirstToken(node.arguments[0], token => token.value === "async"),
- message: "Promise executor functions should not be async."
+ messageId: "async"
});
}
};

lib/rules/no-bitwise.js

@@ -43,7 +43,8 @@
uniqueItems: true
},
int32Hint: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/no-caller.js

@@ -35,7 +35,7 @@
const objectName = node.object.name,
propertyName = node.property.name;
- if (objectName === "arguments" && !node.computed && propertyName && propertyName.match(/^calle[er]$/)) {
+ if (objectName === "arguments" && !node.computed && propertyName && propertyName.match(/^calle[er]$/u)) {
context.report({ node, messageId: "unexpected", data: { prop: propertyName } });
}

lib/rules/no-confusing-arrow.js

@@ -41,7 +41,7 @@
schema: [{
type: "object",
properties: {
- allowParens: { type: "boolean" }
+ allowParens: { type: "boolean", default: false }
},
additionalProperties: false
}],

lib/rules/no-constant-condition.js

@@ -6,6 +6,13 @@
"use strict";
//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+const EQUALITY_OPERATORS = ["===", "!==", "==", "!="];
+const RELATIONAL_OPERATORS = [">", "<", ">=", "<=", "in", "instanceof"];
+
+//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@@ -25,7 +32,8 @@
type: "object",
properties: {
checkLoops: {
- type: "boolean"
+ type: "boolean",
+ default: true
}
},
additionalProperties: false
@@ -109,7 +117,21 @@
const isLeftShortCircuit = (isLeftConstant && isLogicalIdentity(node.left, node.operator));
const isRightShortCircuit = (isRightConstant && isLogicalIdentity(node.right, node.operator));
- return (isLeftConstant && isRightConstant) || isLeftShortCircuit || isRightShortCircuit;
+ return (isLeftConstant && isRightConstant) ||
+ (
+
+ // in the case of an "OR", we need to know if the right constant value is truthy
+ node.operator === "||" &&
+ isRightConstant &&
+ node.right.value &&
+ (
+ !node.parent ||
+ node.parent.type !== "BinaryExpression" ||
+ !(EQUALITY_OPERATORS.includes(node.parent.operator) || RELATIONAL_OPERATORS.includes(node.parent.operator))
+ )
+ ) ||
+ isLeftShortCircuit ||
+ isRightShortCircuit;
}
case "AssignmentExpression":

lib/rules/no-dupe-keys.js

@@ -15,8 +15,8 @@
// Helpers
//------------------------------------------------------------------------------
-const GET_KIND = /^(?:init|get)$/;
-const SET_KIND = /^(?:init|set)$/;
+const GET_KIND = /^(?:init|get)$/u;
+const SET_KIND = /^(?:init|set)$/u;
/**
* The class which stores properties' information of an object.

lib/rules/no-duplicate-imports.js

@@ -29,18 +29,17 @@
* @param {ASTNode} node - A node to get.
* @param {string} value - The name of the imported or exported module.
* @param {string[]} array - The array containing other imports or exports in the file.
- * @param {string} message - A message to be reported after the name of the module
+ * @param {string} messageId - A messageId to be reported after the name of the module
*
* @returns {void} No return value
*/
-function checkAndReport(context, node, value, array, message) {
+function checkAndReport(context, node, value, array, messageId) {
if (array.indexOf(value) !== -1) {
context.report({
node,
- message: "'{{module}}' {{message}}",
+ messageId,
data: {
- module: value,
- message
+ module: value
}
});
}
@@ -66,10 +65,10 @@
const value = getValue(node);
if (value) {
- checkAndReport(context, node, value, importsInFile, "import is duplicated.");
+ checkAndReport(context, node, value, importsInFile, "import");
if (includeExports) {
- checkAndReport(context, node, value, exportsInFile, "import is duplicated as export.");
+ checkAndReport(context, node, value, exportsInFile, "importAs");
}
importsInFile.push(value);
@@ -91,8 +90,8 @@
const value = getValue(node);
if (value) {
- checkAndReport(context, node, value, exportsInFile, "export is duplicated.");
- checkAndReport(context, node, value, importsInFile, "export is duplicated as import.");
+ checkAndReport(context, node, value, exportsInFile, "export");
+ checkAndReport(context, node, value, importsInFile, "exportAs");
exportsInFile.push(value);
}
@@ -114,11 +113,18 @@
type: "object",
properties: {
includeExports: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false
- }]
+ }],
+ messages: {
+ import: "'{{module}}' import is duplicated.",
+ importAs: "'{{module}}' import is duplicated as export.",
+ export: "'{{module}}' export is duplicated.",
+ exportAs: "'{{module}}' export is duplicated as import."
+ }
},
create(context) {

lib/rules/no-else-return.js

@@ -31,7 +31,8 @@
type: "object",
properties: {
allowElseIf: {
- type: "boolean"
+ type: "boolean",
+ default: true
}
},
additionalProperties: false
@@ -81,7 +82,7 @@
* after the if block
*/
const ifBlockMaybeUnsafe = node.parent.consequent.type !== "BlockStatement" && lastIfToken.value !== ";";
- const elseBlockUnsafe = /^[([/+`-]/.test(firstTokenOfElseBlock.value);
+ const elseBlockUnsafe = /^[([/+`-]/u.test(firstTokenOfElseBlock.value);
if (ifBlockMaybeUnsafe && elseBlockUnsafe) {
return null;
@@ -93,7 +94,7 @@
if (lastTokenOfElseBlock.value !== ";") {
const nextToken = sourceCode.getTokenAfter(endToken);
- const nextTokenUnsafe = nextToken && /^[([/+`-]/.test(nextToken.value);
+ const nextTokenUnsafe = nextToken && /^[([/+`-]/u.test(nextToken.value);
const nextTokenOnSameLine = nextToken && nextToken.loc.start.line === lastTokenOfElseBlock.loc.start.line;
/*

lib/rules/no-empty-character-class.js

@@ -21,7 +21,7 @@
* 4. `[gimuy]*`: optional regexp flags
* 5. `$`: fix the match at the end of the string
*/
-const regex = /^\/([^\\[]|\\.|\[([^\\\]]|\\.)+])*\/[gimuys]*$/;
+const regex = /^\/([^\\[]|\\.|\[([^\\\]]|\\.)+\])*\/[gimuys]*$/u;
//------------------------------------------------------------------------------
// Rule Definition

lib/rules/no-empty.js

@@ -30,7 +30,8 @@
type: "object",
properties: {
allowEmptyCatch: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/no-eval.js

@@ -89,7 +89,7 @@
{
type: "object",
properties: {
- allowIndirect: { type: "boolean" }
+ allowIndirect: { type: "boolean", default: false }
},
additionalProperties: false
}

lib/rules/no-extra-parens.js

@@ -471,6 +471,7 @@
const firstToken = isParenthesised(node) ? sourceCode.getTokenBefore(node) : sourceCode.getFirstToken(node);
const secondToken = sourceCode.getTokenAfter(firstToken, astUtils.isNotOpeningParenToken);
const thirdToken = secondToken ? sourceCode.getTokenAfter(secondToken) : null;
+ const tokenAfterClosingParens = secondToken ? sourceCode.getTokenAfter(secondToken, astUtils.isNotClosingParenToken) : null;
if (
astUtils.isOpeningParenToken(firstToken) &&
@@ -479,7 +480,12 @@
secondToken.type === "Keyword" && (
secondToken.value === "function" ||
secondToken.value === "class" ||
- secondToken.value === "let" && astUtils.isOpeningBracketToken(sourceCode.getTokenAfter(secondToken, astUtils.isNotClosingParenToken))
+ secondToken.value === "let" &&
+ tokenAfterClosingParens &&
+ (
+ astUtils.isOpeningBracketToken(tokenAfterClosingParens) ||
+ tokenAfterClosingParens.type === "Identifier"
+ )
) ||
secondToken && secondToken.type === "Identifier" && secondToken.value === "async" && thirdToken && thirdToken.type === "Keyword" && thirdToken.value === "function"
)

lib/rules/no-fallthrough.js

@@ -14,7 +14,7 @@
// Helpers
//------------------------------------------------------------------------------
-const DEFAULT_FALLTHROUGH_COMMENT = /falls?\s?through/i;
+const DEFAULT_FALLTHROUGH_COMMENT = /falls?\s?through/iu;
/**
* Checks whether or not a given node has a fallthrough comment.
@@ -69,12 +69,17 @@
type: "object",
properties: {
commentPattern: {
- type: "string"
+ type: "string",
+ default: ""
}
},
additionalProperties: false
}
- ]
+ ],
+ messages: {
+ case: "Expected a 'break' statement before 'case'.",
+ default: "Expected a 'break' statement before 'default'."
+ }
},
create(context) {
@@ -90,7 +95,7 @@
let fallthroughCommentPattern = null;
if (options.commentPattern) {
- fallthroughCommentPattern = new RegExp(options.commentPattern);
+ fallthroughCommentPattern = new RegExp(options.commentPattern); // eslint-disable-line require-unicode-regexp
} else {
fallthroughCommentPattern = DEFAULT_FALLTHROUGH_COMMENT;
}
@@ -111,8 +116,7 @@
*/
if (fallthroughCase && !hasFallthroughComment(node, context, fallthroughCommentPattern)) {
context.report({
- message: "Expected a 'break' statement before '{{type}}'.",
- data: { type: node.test ? "case" : "default" },
+ messageId: node.test ? "case" : "default",
node
});
}

lib/rules/no-floating-decimal.js

@@ -27,7 +27,11 @@
},
schema: [],
- fixable: "code"
+ fixable: "code",
+ messages: {
+ leading: "A leading decimal point can be confused with a dot.",
+ trailing: "A trailing decimal point can be confused with a dot."
+ }
},
create(context) {
@@ -40,7 +44,7 @@
if (node.raw.startsWith(".")) {
context.report({
node,
- message: "A leading decimal point can be confused with a dot.",
+ messageId: "leading",
fix(fixer) {
const tokenBefore = sourceCode.getTokenBefore(node);
const needsSpaceBefore = tokenBefore &&
@@ -54,7 +58,7 @@
if (node.raw.indexOf(".") === node.raw.length - 1) {
context.report({
node,
- message: "A trailing decimal point can be confused with a dot.",
+ messageId: "trailing",
fix: fixer => fixer.insertTextAfter(node, "0")
});
}

lib/rules/no-implicit-coercion.js

@@ -11,7 +11,7 @@
// Helpers
//------------------------------------------------------------------------------
-const INDEX_OF_PATTERN = /^(?:i|lastI)ndexOf$/;
+const INDEX_OF_PATTERN = /^(?:i|lastI)ndexOf$/u;
const ALLOWABLE_OPERATORS = ["~", "!!", "+", "*"];
/**
@@ -21,9 +21,9 @@
*/
function parseOptions(options) {
return {
- boolean: "boolean" in options ? Boolean(options.boolean) : true,
- number: "number" in options ? Boolean(options.number) : true,
- string: "string" in options ? Boolean(options.string) : true,
+ boolean: "boolean" in options ? options.boolean : true,
+ number: "number" in options ? options.number : true,
+ string: "string" in options ? options.string : true,
allow: options.allow || []
};
}
@@ -167,13 +167,16 @@
type: "object",
properties: {
boolean: {
- type: "boolean"
+ type: "boolean",
+ default: true
},
number: {
- type: "boolean"
+ type: "boolean",
+ default: true
},
string: {
- type: "boolean"
+ type: "boolean",
+ default: true
},
allow: {
type: "array",

lib/rules/no-implied-eval.js

@@ -24,7 +24,7 @@
},
create(context) {
- const CALLEE_RE = /^(setTimeout|setInterval|execScript)$/;
+ const CALLEE_RE = /^(setTimeout|setInterval|execScript)$/u;
/*
* Figures out if we should inspect a given binary expression. Is a stack

lib/rules/no-invalid-regexp.js

@@ -10,7 +10,7 @@
const RegExpValidator = require("regexpp").RegExpValidator;
const validator = new RegExpValidator({ ecmaVersion: 2018 });
-const validFlags = /[gimuys]/g;
+const validFlags = /[gimuys]/gu;
const undefined1 = void 0;
//------------------------------------------------------------------------------
@@ -51,7 +51,7 @@
const temp = options.allowConstructorFlags.join("").replace(validFlags, "");
if (temp) {
- allowedFlags = new RegExp(`[${temp}]`, "gi");
+ allowedFlags = new RegExp(`[${temp}]`, "giu");
}
}

lib/rules/no-irregular-whitespace.js

@@ -16,9 +16,9 @@
// Constants
//------------------------------------------------------------------------------
-const ALL_IRREGULARS = /[\f\v\u0085\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000\u2028\u2029]/;
-const IRREGULAR_WHITESPACE = /[\f\v\u0085\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000]+/mg;
-const IRREGULAR_LINE_TERMINATORS = /[\u2028\u2029]/mg;
+const ALL_IRREGULARS = /[\f\v\u0085\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000\u2028\u2029]/u;
+const IRREGULAR_WHITESPACE = /[\f\v\u0085\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000]+/mgu;
+const IRREGULAR_LINE_TERMINATORS = /[\u2028\u2029]/mgu;
const LINE_BREAK = astUtils.createGlobalLinebreakMatcher();
//------------------------------------------------------------------------------
@@ -41,16 +41,20 @@
type: "object",
properties: {
skipComments: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
skipStrings: {
- type: "boolean"
+ type: "boolean",
+ default: true
},
skipTemplates: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
skipRegExps: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/no-labels.js

@@ -30,10 +30,12 @@
type: "object",
properties: {
allowLoop: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
allowSwitch: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false
@@ -43,8 +45,8 @@
create(context) {
const options = context.options[0];
- const allowLoop = Boolean(options && options.allowLoop);
- const allowSwitch = Boolean(options && options.allowSwitch);
+ const allowLoop = options && options.allowLoop;
+ const allowSwitch = options && options.allowSwitch;
let scopeInfo = null;
/**

lib/rules/no-lonely-if.js

@@ -58,7 +58,7 @@
node.consequent.type !== "BlockStatement" && lastIfToken.value !== ";" && tokenAfterElseBlock &&
(
node.consequent.loc.end.line === tokenAfterElseBlock.loc.start.line ||
- /^[([/+`-]/.test(tokenAfterElseBlock.value) ||
+ /^[([/+`-]/u.test(tokenAfterElseBlock.value) ||
lastIfToken.value === "++" ||
lastIfToken.value === "--"
)

lib/rules/no-magic-numbers.js

@@ -24,10 +24,12 @@
type: "object",
properties: {
detectObjects: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
enforceConst: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
ignore: {
type: "array",
@@ -37,7 +39,8 @@
uniqueItems: true
},
ignoreArrayIndexes: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/no-mixed-operators.js

@@ -34,7 +34,7 @@
LOGICAL_OPERATORS,
RELATIONAL_OPERATORS
];
-const TARGET_NODE_TYPE = /^(?:Binary|Logical)Expression$/;
+const TARGET_NODE_TYPE = /^(?:Binary|Logical)Expression$/u;
/**
* Normalizes options.
@@ -42,10 +42,10 @@
* @param {Object|undefined} options - A options object to normalize.
* @returns {Object} Normalized option object.
*/
-function normalizeOptions(options) {
- const hasGroups = (options && options.groups && options.groups.length > 0);
+function normalizeOptions(options = {}) {
+ const hasGroups = options.groups && options.groups.length > 0;
const groups = hasGroups ? options.groups : DEFAULT_GROUPS;
- const allowSamePrecedence = (options && options.allowSamePrecedence) !== false;
+ const allowSamePrecedence = options.allowSamePrecedence !== false;
return {
groups,
@@ -95,7 +95,8 @@
uniqueItems: true
},
allowSamePrecedence: {
- type: "boolean"
+ type: "boolean",
+ default: true
}
},
additionalProperties: false

lib/rules/no-mixed-requires.js

@@ -156,7 +156,7 @@
// "var fs = require('fs');"
return REQ_CORE;
}
- if (/^\.{0,2}\//.test(arg.value)) {
+ if (/^\.{0,2}\//u.test(arg.value)) {
// "var utils = require('./utils');"
return REQ_FILE;

lib/rules/no-mixed-spaces-and-tabs.js

@@ -88,7 +88,7 @@
* or the reverse before non-tab/-space
* characters begin.
*/
- let regex = /^(?=[\t ]*(\t | \t))/;
+ let regex = /^(?=[\t ]*(\t | \t))/u;
const lines = sourceCode.lines,
comments = sourceCode.getAllComments();
@@ -114,7 +114,7 @@
* At least one space followed by a tab
* before non-tab/-space characters begin.
*/
- regex = /^(?=[\t ]* \t)/;
+ regex = /^(?=[\t ]* \t)/u;
}
lines.forEach((line, i) => {

lib/rules/no-multi-spaces.js

@@ -38,7 +38,8 @@
additionalProperties: false
},
ignoreEOLComments: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/no-octal-escape.js

@@ -32,7 +32,7 @@
return;
}
- const match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-3][0-7]{1,2}|[4-7][0-7]|[0-7])/);
+ const match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-3][0-7]{1,2}|[4-7][0-7]|[0-7])/u);
if (match) {
const octalDigit = match[2];

lib/rules/no-octal.js

@@ -28,7 +28,7 @@
return {
Literal(node) {
- if (typeof node.value === "number" && /^0[0-7]/.test(node.raw)) {
+ if (typeof node.value === "number" && /^0[0-7]/u.test(node.raw)) {
context.report({ node, message: "Octal literals should not be used." });
}
}

lib/rules/no-param-reassign.js

@@ -8,7 +8,7 @@
// Rule Definition
//------------------------------------------------------------------------------
-const stopNodePattern = /(?:Statement|Declaration|Function(?:Expression)?|Program)$/;
+const stopNodePattern = /(?:Statement|Declaration|Function(?:Expression)?|Program)$/u;
module.exports = {
meta: {
@@ -55,7 +55,7 @@
},
create(context) {
- const props = context.options[0] && Boolean(context.options[0].props);
+ const props = context.options[0] && context.options[0].props;
const ignoredPropertyAssignmentsFor = context.options[0] && context.options[0].ignorePropertyModificationsFor || [];
/**

lib/rules/no-path-concat.js

@@ -24,7 +24,7 @@
create(context) {
- const MATCHER = /^__(?:dir|file)name$/;
+ const MATCHER = /^__(?:dir|file)name$/u;
//--------------------------------------------------------------------------
// Public

lib/rules/no-plusplus.js

@@ -26,7 +26,8 @@
type: "object",
properties: {
allowForLoopAfterthoughts: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/no-redeclare.js

@@ -24,7 +24,7 @@
{
type: "object",
properties: {
- builtinGlobals: { type: "boolean" }
+ builtinGlobals: { type: "boolean", default: false }
},
additionalProperties: false
}
@@ -33,7 +33,7 @@
create(context) {
const options = {
- builtinGlobals: Boolean(context.options[0] && context.options[0].builtinGlobals)
+ builtinGlobals: context.options[0] && context.options[0].builtinGlobals
};
/**

lib/rules/no-regex-spaces.js

@@ -39,7 +39,7 @@
* @private
*/
function checkRegex(node, value, valueStart) {
- const multipleSpacesRegex = /( {2,})( [+*{?]|[^+*{?]|$)/,
+ const multipleSpacesRegex = /( {2,})( [+*{?]|[^+*{?]|$)/u,
regexResults = multipleSpacesRegex.exec(value);
if (regexResults !== null) {

lib/rules/no-return-assign.js

@@ -14,7 +14,7 @@
// Helpers
//------------------------------------------------------------------------------
-const SENTINEL_TYPE = /^(?:[a-zA-Z]+?Statement|ArrowFunctionExpression|FunctionExpression|ClassExpression)$/;
+const SENTINEL_TYPE = /^(?:[a-zA-Z]+?Statement|ArrowFunctionExpression|FunctionExpression|ClassExpression)$/u;
//------------------------------------------------------------------------------
// Rule Definition

lib/rules/no-self-assign.js

@@ -15,7 +15,7 @@
// Helpers
//------------------------------------------------------------------------------
-const SPACES = /\s+/g;
+const SPACES = /\s+/gu;
/**
* Checks whether the property of 2 given member expression nodes are the same
@@ -179,7 +179,8 @@
type: "object",
properties: {
props: {
- type: "boolean"
+ type: "boolean",
+ default: true
}
},
additionalProperties: false

lib/rules/no-shadow.js

@@ -30,8 +30,8 @@
{
type: "object",
properties: {
- builtinGlobals: { type: "boolean" },
- hoist: { enum: ["all", "functions", "never"] },
+ builtinGlobals: { type: "boolean", default: false },
+ hoist: { enum: ["all", "functions", "never"], default: "functions" },
allow: {
type: "array",
items: {
@@ -47,7 +47,7 @@
create(context) {
const options = {
- builtinGlobals: Boolean(context.options[0] && context.options[0].builtinGlobals),
+ builtinGlobals: context.options[0] && context.options[0].builtinGlobals,
hoist: (context.options[0] && context.options[0].hoist) || "functions",
allow: (context.options[0] && context.options[0].allow) || []
};

lib/rules/no-shadow-restricted-names.js

@@ -4,6 +4,19 @@
*/
"use strict";
+/**
+ * Determines if a variable safely shadows undefined.
+ * This is the case when a variable named `undefined` is never assigned to a value (i.e. it always shares the same value
+ * as the global).
+ * @param {eslintScope.Variable} variable The variable to check
+ * @returns {boolean} true if this variable safely shadows `undefined`
+ */
+function safelyShadowsUndefined(variable) {
+ return variable.name === "undefined" &&
+ variable.references.every(ref => !ref.isWrite()) &&
+ variable.defs.every(def => def.node.type === "VariableDeclarator" && def.node.init === null);
+}
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@@ -24,12 +37,13 @@
create(context) {
- const RESTRICTED = ["undefined", "NaN", "Infinity", "arguments", "eval"];
+
+ const RESTRICTED = new Set(["undefined", "NaN", "Infinity", "arguments", "eval"]);
return {
"VariableDeclaration, :function, CatchClause"(node) {
for (const variable of context.getDeclaredVariables(node)) {
- if (variable.defs.length > 0 && RESTRICTED.includes(variable.name)) {
+ if (variable.defs.length > 0 && RESTRICTED.has(variable.name) && !safelyShadowsUndefined(variable)) {
context.report({
node: variable.defs[0].name,
message: "Shadowing of global property '{{idName}}'.",

lib/rules/no-sync.js

@@ -27,7 +27,8 @@
type: "object",
properties: {
allowAtRootLevel: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/no-tabs.js

@@ -9,8 +9,8 @@
// Helpers
//------------------------------------------------------------------------------
-const tabRegex = /\t+/g;
-const anyNonWhitespaceRegex = /\S/;
+const tabRegex = /\t+/gu;
+const anyNonWhitespaceRegex = /\S/u;
//------------------------------------------------------------------------------
// Public Interface
@@ -30,7 +30,8 @@
type: "object",
properties: {
allowIndentationTabs: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/no-template-curly-in-string.js

@@ -23,7 +23,7 @@
},
create(context) {
- const regex = /\$\{[^}]+\}/;
+ const regex = /\$\{[^}]+\}/u;
return {
Literal(node) {

lib/rules/no-trailing-spaces.js

@@ -32,10 +32,12 @@
type: "object",
properties: {
skipBlankLines: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
ignoreComments: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false
@@ -52,7 +54,7 @@
const options = context.options[0] || {},
skipBlankLines = options.skipBlankLines || false,
- ignoreComments = typeof options.ignoreComments === "boolean" && options.ignoreComments;
+ ignoreComments = options.ignoreComments || false;
/**
* Report the error message
@@ -109,8 +111,8 @@
* fetch the source code and do matching via regexps.
*/
- const re = new RegExp(NONBLANK),
- skipMatch = new RegExp(SKIP_BLANK),
+ const re = new RegExp(NONBLANK, "u"),
+ skipMatch = new RegExp(SKIP_BLANK, "u"),
lines = sourceCode.lines,
linebreaks = sourceCode.getText().match(astUtils.createGlobalLinebreakMatcher()),
comments = sourceCode.getAllComments(),

lib/rules/no-undef.js

@@ -39,12 +39,16 @@
type: "object",
properties: {
typeof: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false
}
- ]
+ ],
+ messages: {
+ undef: "'{{name}}' is not defined."
+ }
},
create(context) {
@@ -64,7 +68,7 @@
context.report({
node: identifier,
- message: "'{{name}}' is not defined.",
+ messageId: "undef",
data: identifier
});
});

lib/rules/no-underscore-dangle.js

@@ -31,13 +31,16 @@
}
},
allowAfterThis: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
allowAfterSuper: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
enforceInMethodNames: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/no-unexpected-multiline.js

@@ -25,17 +25,18 @@
url: "https://eslint.org/docs/rules/no-unexpected-multiline"
},
- schema: []
+ schema: [],
+ messages: {
+ function: "Unexpected newline between function and ( of function call.",
+ property: "Unexpected newline between object and [ of property access.",
+ taggedTemplate: "Unexpected newline between template tag and template literal.",
+ division: "Unexpected newline between numerator and division operator."
+ }
},
create(context) {
- const FUNCTION_MESSAGE = "Unexpected newline between function and ( of function call.";
- const PROPERTY_MESSAGE = "Unexpected newline between object and [ of property access.";
- const TAGGED_TEMPLATE_MESSAGE = "Unexpected newline between template tag and template literal.";
- const DIVISION_MESSAGE = "Unexpected newline between numerator and division operator.";
-
- const REGEX_FLAG_MATCHER = /^[gimsuy]+$/;
+ const REGEX_FLAG_MATCHER = /^[gimsuy]+$/u;
const sourceCode = context.getSourceCode();
@@ -43,16 +44,16 @@
* Check to see if there is a newline between the node and the following open bracket
* line's expression
* @param {ASTNode} node The node to check.
- * @param {string} msg The error message to use.
+ * @param {string} messageId The error messageId to use.
* @returns {void}
* @private
*/
- function checkForBreakAfter(node, msg) {
+ function checkForBreakAfter(node, messageId) {
const openParen = sourceCode.getTokenAfter(node, astUtils.isNotClosingParenToken);
const nodeExpressionEnd = sourceCode.getTokenBefore(openParen);
if (openParen.loc.start.line !== nodeExpressionEnd.loc.end.line) {
- context.report({ node, loc: openParen.loc.start, message: msg, data: { char: openParen.value } });
+ context.report({ node, loc: openParen.loc.start, messageId, data: { char: openParen.value } });
}
}
@@ -66,21 +67,21 @@
if (!node.computed) {
return;
}
- checkForBreakAfter(node.object, PROPERTY_MESSAGE);
+ checkForBreakAfter(node.object, "property");
},
TaggedTemplateExpression(node) {
if (node.tag.loc.end.line === node.quasi.loc.start.line) {
return;
}
- context.report({ node, loc: node.loc.start, message: TAGGED_TEMPLATE_MESSAGE });
+ context.report({ node, loc: node.loc.start, messageId: "taggedTemplate" });
},
CallExpression(node) {
if (node.arguments.length === 0) {
return;
}
- checkForBreakAfter(node.callee, FUNCTION_MESSAGE);
+ checkForBreakAfter(node.callee, "function");
},
"BinaryExpression[operator='/'] > BinaryExpression[operator='/'].left"(node) {
@@ -92,7 +93,7 @@
REGEX_FLAG_MATCHER.test(tokenAfterOperator.value) &&
secondSlash.range[1] === tokenAfterOperator.range[0]
) {
- checkForBreakAfter(node.left, DIVISION_MESSAGE);
+ checkForBreakAfter(node.left, "division");
}
}
};

lib/rules/no-unmodified-loop-condition.js

@@ -16,11 +16,11 @@
// Helpers
//------------------------------------------------------------------------------
-const SENTINEL_PATTERN = /(?:(?:Call|Class|Function|Member|New|Yield)Expression|Statement|Declaration)$/;
-const LOOP_PATTERN = /^(?:DoWhile|For|While)Statement$/; // for-in/of statements don't have `test` property.
-const GROUP_PATTERN = /^(?:BinaryExpression|ConditionalExpression)$/;
-const SKIP_PATTERN = /^(?:ArrowFunction|Class|Function)Expression$/;
-const DYNAMIC_PATTERN = /^(?:Call|Member|New|TaggedTemplate|Yield)Expression$/;
+const SENTINEL_PATTERN = /(?:(?:Call|Class|Function|Member|New|Yield)Expression|Statement|Declaration)$/u;
+const LOOP_PATTERN = /^(?:DoWhile|For|While)Statement$/u; // for-in/of statements don't have `test` property.
+const GROUP_PATTERN = /^(?:BinaryExpression|ConditionalExpression)$/u;
+const SKIP_PATTERN = /^(?:ArrowFunction|Class|Function)Expression$/u;
+const DYNAMIC_PATTERN = /^(?:Call|Member|New|TaggedTemplate|Yield)Expression$/u;
/**
* @typedef {Object} LoopConditionInfo

lib/rules/no-unneeded-ternary.js

@@ -38,7 +38,8 @@
type: "object",
properties: {
defaultAssignment: {
- type: "boolean"
+ type: "boolean",
+ default: true
}
},
additionalProperties: false

lib/rules/no-unsafe-finally.js

@@ -9,9 +9,9 @@
// Helpers
//------------------------------------------------------------------------------
-const SENTINEL_NODE_TYPE_RETURN_THROW = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression)$/;
-const SENTINEL_NODE_TYPE_BREAK = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement|SwitchStatement)$/;
-const SENTINEL_NODE_TYPE_CONTINUE = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement)$/;
+const SENTINEL_NODE_TYPE_RETURN_THROW = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression)$/u;
+const SENTINEL_NODE_TYPE_BREAK = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement|SwitchStatement)$/u;
+const SENTINEL_NODE_TYPE_CONTINUE = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement)$/u;
//------------------------------------------------------------------------------

lib/rules/no-unsafe-negation.js

@@ -51,7 +51,10 @@
},
schema: [],
- fixable: "code"
+ fixable: "code",
+ messages: {
+ unexpected: "Unexpected negating the left operand of '{{operator}}' operator."
+ }
},
create(context) {
@@ -66,8 +69,8 @@
context.report({
node,
loc: node.left.loc,
- message: "Unexpected negating the left operand of '{{operator}}' operator.",
- data: node,
+ messageId: "unexpected",
+ data: { operator: node.operator },
fix(fixer) {
const negationToken = sourceCode.getFirstToken(node.left);

lib/rules/no-unused-expressions.js

@@ -24,13 +24,16 @@
type: "object",
properties: {
allowShortCircuit: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
allowTernary: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
allowTaggedTemplates: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false
@@ -85,7 +88,7 @@
grandparent = ancestors[ancestors.length - 2];
return (parent.type === "Program" || parent.type === "BlockStatement" &&
- (/Function/.test(grandparent.type))) &&
+ (/Function/u.test(grandparent.type))) &&
directives(parent).indexOf(node) >= 0;
}
@@ -113,7 +116,7 @@
return true;
}
- return /^(?:Assignment|Call|New|Update|Yield|Await)Expression$/.test(node.type) ||
+ return /^(?:Assignment|Call|New|Update|Yield|Await)Expression$/u.test(node.type) ||
(node.type === "UnaryExpression" && ["delete", "void"].indexOf(node.operator) >= 0);
}

lib/rules/no-unused-labels.js

@@ -21,7 +21,12 @@
},
schema: [],
- fixable: "code"
+
+ fixable: "code",
+
+ messages: {
+ unused: "'{{name}}:' is defined but never used."
+ }
},
create(context) {
@@ -53,7 +58,7 @@
if (!scopeInfo.used) {
context.report({
node: node.label,
- message: "'{{name}}:' is defined but never used.",
+ messageId: "unused",
data: node.label,
fix(fixer) {

lib/rules/no-unused-vars.js

@@ -67,7 +67,7 @@
create(context) {
const sourceCode = context.getSourceCode();
- const REST_PROPERTY_TYPE = /^(?:RestElement|(?:Experimental)?RestProperty)$/;
+ const REST_PROPERTY_TYPE = /^(?:RestElement|(?:Experimental)?RestProperty)$/u;
const config = {
vars: "all",
@@ -88,15 +88,15 @@
config.caughtErrors = firstOption.caughtErrors || config.caughtErrors;
if (firstOption.varsIgnorePattern) {
- config.varsIgnorePattern = new RegExp(firstOption.varsIgnorePattern);
+ config.varsIgnorePattern = new RegExp(firstOption.varsIgnorePattern); // eslint-disable-line require-unicode-regexp
}
if (firstOption.argsIgnorePattern) {
- config.argsIgnorePattern = new RegExp(firstOption.argsIgnorePattern);
+ config.argsIgnorePattern = new RegExp(firstOption.argsIgnorePattern); // eslint-disable-line require-unicode-regexp
}
if (firstOption.caughtErrorsIgnorePattern) {
- config.caughtErrorsIgnorePattern = new RegExp(firstOption.caughtErrorsIgnorePattern);
+ config.caughtErrorsIgnorePattern = new RegExp(firstOption.caughtErrorsIgnorePattern); // eslint-disable-line require-unicode-regexp
}
}
}
@@ -143,7 +143,7 @@
// Helpers
//--------------------------------------------------------------------------
- const STATEMENT_TYPE = /(?:Statement|Declaration)$/;
+ const STATEMENT_TYPE = /(?:Statement|Declaration)$/u;
/**
* Determines if a given variable is being exported from a module.
@@ -596,7 +596,7 @@
* @private
*/
function getColumnInComment(variable, comment) {
- const namePattern = new RegExp(`[\\s,]${lodash.escapeRegExp(variable.name)}(?:$|[\\s,:])`, "g");
+ const namePattern = new RegExp(`[\\s,]${lodash.escapeRegExp(variable.name)}(?:$|[\\s,:])`, "gu");
// To ignore the first text "global".
namePattern.lastIndex = comment.value.indexOf("global") + 6;

lib/rules/no-use-before-define.js

@@ -9,8 +9,8 @@
// Helpers
//------------------------------------------------------------------------------
-const SENTINEL_TYPE = /^(?:(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|CatchClause|ImportDeclaration|ExportNamedDeclaration)$/;
-const FOR_IN_OF_TYPE = /^For(?:In|Of)Statement$/;
+const SENTINEL_TYPE = /^(?:(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|CatchClause|ImportDeclaration|ExportNamedDeclaration)$/u;
+const FOR_IN_OF_TYPE = /^For(?:In|Of)Statement$/u;
/**
* Parses a given value as options.

lib/rules/no-useless-escape.js

@@ -181,7 +181,7 @@
}
const value = isTemplateElement ? node.value.raw : node.raw.slice(1, -1);
- const pattern = /\\[^\d]/g;
+ const pattern = /\\[^\d]/gu;
let match;
while ((match = pattern.exec(value))) {

lib/rules/no-useless-rename.js

@@ -26,9 +26,9 @@
{
type: "object",
properties: {
- ignoreDestructuring: { type: "boolean" },
- ignoreImport: { type: "boolean" },
- ignoreExport: { type: "boolean" }
+ ignoreDestructuring: { type: "boolean", default: false },
+ ignoreImport: { type: "boolean", default: false },
+ ignoreExport: { type: "boolean", default: false }
},
additionalProperties: false
}

lib/rules/no-var.js

@@ -77,7 +77,7 @@
return node.declarations.every(declarator => declarator.init !== null);
}
-const SCOPE_NODE_TYPE = /^(?:Program|BlockStatement|SwitchStatement|ForStatement|ForInStatement|ForOfStatement)$/;
+const SCOPE_NODE_TYPE = /^(?:Program|BlockStatement|SwitchStatement|ForStatement|ForInStatement|ForOfStatement)$/u;
/**
* Gets the scope node which directly contains a given node.

lib/rules/no-warning-comments.js

@@ -47,7 +47,7 @@
configuration = context.options[0] || {},
warningTerms = configuration.terms || ["todo", "fixme", "xxx"],
location = configuration.location || "start",
- selfConfigRegEx = /\bno-warning-comments\b/;
+ selfConfigRegEx = /\bno-warning-comments\b/u;
/**
* Convert a warning term into a RegExp which will match a comment containing that whole word in the specified
@@ -58,7 +58,7 @@
* @returns {RegExp} The term converted to a RegExp
*/
function convertToRegExp(term) {
- const escaped = term.replace(/[-/\\$^*+?.()|[\]{}]/g, "\\$&");
+ const escaped = term.replace(/[-/\\$^*+?.()|[\]{}]/gu, "\\$&");
const wordBoundary = "\\b";
const eitherOrWordBoundary = `|${wordBoundary}`;
let prefix;
@@ -73,7 +73,7 @@
* In these cases, use no bounding match. Same applies for the
* prefix, handled below.
*/
- const suffix = /\w$/.test(term) ? "\\b" : "";
+ const suffix = /\w$/u.test(term) ? "\\b" : "";
if (location === "start") {
@@ -82,7 +82,7 @@
* there's no need to worry about word boundaries.
*/
prefix = "^\\s*";
- } else if (/^\w/.test(term)) {
+ } else if (/^\w/u.test(term)) {
prefix = wordBoundary;
} else {
prefix = "";
@@ -95,7 +95,7 @@
* ^\s*TERM\b. This checks the word boundary
* at the beginning of the comment.
*/
- return new RegExp(prefix + escaped + suffix, "i");
+ return new RegExp(prefix + escaped + suffix, "i"); // eslint-disable-line require-unicode-regexp
}
/*
@@ -103,7 +103,7 @@
* \bTERM\b|\bTERM\b, this checks the entire comment
* for the term.
*/
- return new RegExp(prefix + escaped + suffix + eitherOrWordBoundary + term + wordBoundary, "i");
+ return new RegExp(prefix + escaped + suffix + eitherOrWordBoundary + term + wordBoundary, "i"); // eslint-disable-line require-unicode-regexp
}
const warningRegExps = warningTerms.map(convertToRegExp);

lib/rules/object-property-newline.js

@@ -25,10 +25,12 @@
type: "object",
properties: {
allowAllPropertiesOnSameLine: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
allowMultiplePropertiesPerLine: { // Deprecated
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false
@@ -40,7 +42,7 @@
create(context) {
const allowSameLine = context.options[0] && (
- (Boolean(context.options[0].allowAllPropertiesOnSameLine) || Boolean(context.options[0].allowMultiplePropertiesPerLine)) // Deprecated
+ (context.options[0].allowAllPropertiesOnSameLine || context.options[0].allowMultiplePropertiesPerLine /* Deprecated */)
);
const errorMessage = allowSameLine
? "Object properties must go on a new line if they aren't all on the same line."

lib/rules/object-shorthand.js

@@ -255,7 +255,7 @@
keyPrefix + keyText + sourceCode.text.slice(tokenBeforeParams.range[1], node.value.range[1])
);
}
- const arrowToken = sourceCode.getTokens(node.value).find(token => token.value === "=>");
+ const arrowToken = sourceCode.getTokenBefore(node.value.body, { filter: token => token.value === "=>" });
const tokenBeforeArrow = sourceCode.getTokenBefore(arrowToken);
const hasParensAroundParameters = tokenBeforeArrow.type === "Punctuator" && tokenBeforeArrow.value === ")";
const oldParamText = sourceCode.text.slice(sourceCode.getFirstToken(node.value, node.value.async ? 1 : 0).range[0], tokenBeforeArrow.range[1]);

lib/rules/one-var.js

@@ -32,7 +32,8 @@
type: "object",
properties: {
separateRequires: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
var: {
enum: ["always", "never", "consecutive"]
@@ -76,42 +77,16 @@
options.let = { uninitialized: mode, initialized: mode };
options.const = { uninitialized: mode, initialized: mode };
} else if (typeof mode === "object") { // options configuration is an object
- if (Object.prototype.hasOwnProperty.call(mode, "separateRequires")) {
- options.separateRequires = !!mode.separateRequires;
- }
- if (Object.prototype.hasOwnProperty.call(mode, "var")) {
+ options.separateRequires = mode.separateRequires;
options.var = { uninitialized: mode.var, initialized: mode.var };
- }
- if (Object.prototype.hasOwnProperty.call(mode, "let")) {
options.let = { uninitialized: mode.let, initialized: mode.let };
- }
- if (Object.prototype.hasOwnProperty.call(mode, "const")) {
options.const = { uninitialized: mode.const, initialized: mode.const };
- }
if (Object.prototype.hasOwnProperty.call(mode, "uninitialized")) {
- if (!options.var) {
- options.var = {};
- }
- if (!options.let) {
- options.let = {};
- }
- if (!options.const) {
- options.const = {};
- }
options.var.uninitialized = mode.uninitialized;
options.let.uninitialized = mode.uninitialized;
options.const.uninitialized = mode.uninitialized;
}
if (Object.prototype.hasOwnProperty.call(mode, "initialized")) {
- if (!options.var) {
- options.var = {};
- }
- if (!options.let) {
- options.let = {};
- }
- if (!options.const) {
- options.const = {};
- }
options.var.initialized = mode.initialized;
options.let.initialized = mode.initialized;
options.const.initialized = mode.initialized;
@@ -257,9 +232,11 @@
if (currentOptions.uninitialized === MODE_ALWAYS && currentOptions.initialized === MODE_ALWAYS) {
if (currentScope.uninitialized || currentScope.initialized) {
+ if (!hasRequires) {
return false;
}
}
+ }
if (declarationCounts.uninitialized > 0) {
if (currentOptions.uninitialized === MODE_ALWAYS && currentScope.uninitialized) {
@@ -268,9 +245,11 @@
}
if (declarationCounts.initialized > 0) {
if (currentOptions.initialized === MODE_ALWAYS && currentScope.initialized) {
+ if (!hasRequires) {
return false;
}
}
+ }
if (currentScope.required && hasRequires) {
return false;
}
@@ -340,7 +319,11 @@
* y`
* ^ afterComma
*/
- if (afterComma.loc.start.line > tokenAfterDeclarator.loc.end.line || afterComma.type === "Line" || afterComma.type === "Block") {
+ if (
+ afterComma.loc.start.line > tokenAfterDeclarator.loc.end.line ||
+ afterComma.type === "Line" ||
+ afterComma.type === "Block"
+ ) {
let lastComment = afterComma;
while (lastComment.type === "Line" || lastComment.type === "Block") {
@@ -349,7 +332,7 @@
return fixer.replaceTextRange(
[tokenAfterDeclarator.range[0], lastComment.range[0]],
- `;\n${sourceCode.text.slice(tokenAfterDeclarator.range[1], lastComment.range[0])}\n${declaration.kind} `
+ `;${sourceCode.text.slice(tokenAfterDeclarator.range[1], lastComment.range[0])}${declaration.kind} `
);
}

lib/rules/operator-assignment.js

@@ -104,7 +104,11 @@
}
],
- fixable: "code"
+ fixable: "code",
+ messages: {
+ replaced: "Assignment can be replaced with operator assignment.",
+ unexpected: "Unexpected operator assignment shorthand."
+ }
},
create(context) {
@@ -138,7 +142,7 @@
if (same(left, expr.left)) {
context.report({
node,
- message: "Assignment can be replaced with operator assignment.",
+ messageId: "replaced",
fix(fixer) {
if (canBeFixed(left)) {
const equalsToken = getOperatorToken(node);
@@ -160,7 +164,7 @@
*/
context.report({
node,
- message: "Assignment can be replaced with operator assignment."
+ messageId: "replaced"
});
}
}
@@ -175,7 +179,7 @@
if (node.operator !== "=") {
context.report({
node,
- message: "Unexpected operator assignment shorthand.",
+ messageId: "unexpected",
fix(fixer) {
if (canBeFixed(node.left)) {
const operatorToken = getOperatorToken(node);

lib/rules/padded-blocks.js

@@ -6,6 +6,12 @@
"use strict";
//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("../util/ast-utils");
+
+//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@@ -45,32 +51,45 @@
minProperties: 1
}
]
+ },
+ {
+ type: "object",
+ properties: {
+ allowSingleLineBlocks: {
+ type: "boolean"
+ }
+ }
}
]
},
create(context) {
const options = {};
- const config = context.options[0] || "always";
+ const typeOptions = context.options[0] || "always";
+ const exceptOptions = context.options[1] || {};
- if (typeof config === "string") {
- const shouldHavePadding = config === "always";
+ if (typeof typeOptions === "string") {
+ const shouldHavePadding = typeOptions === "always";
options.blocks = shouldHavePadding;
options.switches = shouldHavePadding;
options.classes = shouldHavePadding;
} else {
- if (Object.prototype.hasOwnProperty.call(config, "blocks")) {
- options.blocks = config.blocks === "always";
+ if (Object.prototype.hasOwnProperty.call(typeOptions, "blocks")) {
+ options.blocks = typeOptions.blocks === "always";
}
- if (Object.prototype.hasOwnProperty.call(config, "switches")) {
- options.switches = config.switches === "always";
+ if (Object.prototype.hasOwnProperty.call(typeOptions, "switches")) {
+ options.switches = typeOptions.switches === "always";
}
- if (Object.prototype.hasOwnProperty.call(config, "classes")) {
- options.classes = config.classes === "always";
+ if (Object.prototype.hasOwnProperty.call(typeOptions, "classes")) {
+ options.classes = typeOptions.classes === "always";
}
}
+ if (Object.prototype.hasOwnProperty.call(exceptOptions, "allowSingleLineBlocks")) {
+ options.allowSingleLineBlocks = exceptOptions.allowSingleLineBlocks === true;
+ }
+
const ALWAYS_MESSAGE = "Block must be padded by blank lines.",
NEVER_MESSAGE = "Block must not be padded by blank lines.";
@@ -177,6 +196,10 @@
blockHasTopPadding = isPaddingBetweenTokens(tokenBeforeFirst, firstBlockToken),
blockHasBottomPadding = isPaddingBetweenTokens(lastBlockToken, tokenAfterLast);
+ if (options.allowSingleLineBlocks && astUtils.isTokenOnSameLine(tokenBeforeFirst, tokenAfterLast)) {
+ return;
+ }
+
if (requirePaddingFor(node)) {
if (!blockHasTopPadding) {
context.report({

lib/rules/padding-line-between-statements.js

@@ -17,10 +17,11 @@
const LT = `[${Array.from(astUtils.LINEBREAKS).join("")}]`;
const PADDING_LINE_SEQUENCE = new RegExp(
- String.raw`^(\s*?${LT})\s*${LT}(\s*;?)$`
+ String.raw`^(\s*?${LT})\s*${LT}(\s*;?)$`,
+ "u"
);
-const CJS_EXPORT = /^(?:module\s*\.\s*)?exports(?:\s*\.|\s*\[|$)/;
-const CJS_IMPORT = /^require\(/;
+const CJS_EXPORT = /^(?:module\s*\.\s*)?exports(?:\s*\.|\s*\[|$)/u;
+const CJS_IMPORT = /^require\(/u;
/**
* Creates tester which check if a node starts with specific keyword.

lib/rules/prefer-arrow-callback.js

@@ -146,10 +146,12 @@
type: "object",
properties: {
allowNamedFunctions: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
allowUnboundThis: {
- type: "boolean"
+ type: "boolean",
+ default: true
}
},
additionalProperties: false

lib/rules/prefer-const.js

@@ -11,9 +11,9 @@
// Helpers
//------------------------------------------------------------------------------
-const PATTERN_TYPE = /^(?:.+?Pattern|RestElement|SpreadProperty|ExperimentalRestProperty|Property)$/;
-const DECLARATION_HOST_TYPE = /^(?:Program|BlockStatement|SwitchCase)$/;
-const DESTRUCTURING_HOST_TYPE = /^(?:VariableDeclarator|AssignmentExpression)$/;
+const PATTERN_TYPE = /^(?:.+?Pattern|RestElement|SpreadProperty|ExperimentalRestProperty|Property)$/u;
+const DECLARATION_HOST_TYPE = /^(?:Program|BlockStatement|SwitchCase)$/u;
+const DESTRUCTURING_HOST_TYPE = /^(?:VariableDeclarator|AssignmentExpression)$/u;
/**
* Checks whether a given node is located at `ForStatement.init` or not.
@@ -345,12 +345,15 @@
{
type: "object",
properties: {
- destructuring: { enum: ["any", "all"] },
- ignoreReadBeforeAssign: { type: "boolean" }
+ destructuring: { enum: ["any", "all"], default: "any" },
+ ignoreReadBeforeAssign: { type: "boolean", default: false }
},
additionalProperties: false
}
- ]
+ ],
+ messages: {
+ useConst: "'{{name}}' is never reassigned. Use 'const' instead."
+ }
},
create(context) {
@@ -445,7 +448,7 @@
nodesToReport.forEach(node => {
context.report({
node,
- message: "'{{name}}' is never reassigned. Use 'const' instead.",
+ messageId: "useConst",
data: node,
fix: shouldFix ? fixer => fixer.replaceText(sourceCode.getFirstToken(varDeclParent), "const") : null
});

lib/rules/prefer-destructuring.js

@@ -19,6 +19,8 @@
url: "https://eslint.org/docs/rules/prefer-destructuring"
},
+ fixable: "code",
+
schema: [
{
@@ -130,10 +132,55 @@
*
* @param {ASTNode} reportNode the node to report
* @param {string} type the type of destructuring that should have been done
+ * @param {Function|null} fix the fix function or null to pass to context.report
* @returns {void}
*/
- function report(reportNode, type) {
- context.report({ node: reportNode, message: "Use {{type}} destructuring.", data: { type } });
+ function report(reportNode, type, fix) {
+ context.report({
+ node: reportNode,
+ message: "Use {{type}} destructuring.",
+ data: { type },
+ fix
+ });
+ }
+
+ /**
+ * Determines if a node should be fixed into object destructuring
+ *
+ * The fixer only fixes the simplest case of object destructuring,
+ * like: `let x = a.x`;
+ *
+ * Assignment expression is not fixed.
+ * Array destructuring is not fixed.
+ * Renamed property is not fixed.
+ *
+ * @param {ASTNode} node the the node to evaluate
+ * @returns {boolean} whether or not the node should be fixed
+ */
+ function shouldFix(node) {
+ return node.type === "VariableDeclarator" &&
+ node.id.type === "Identifier" &&
+ node.init.type === "MemberExpression" &&
+ node.id.name === node.init.property.name;
+ }
+
+ /**
+ * Fix a node into object destructuring.
+ * This function only handles the simplest case of object destructuring,
+ * see {@link shouldFix}.
+ *
+ * @param {SourceCodeFixer} fixer the fixer object
+ * @param {ASTNode} node the node to be fixed.
+ * @returns {Object} a fix for the node
+ */
+ function fixIntoObjectDestructuring(fixer, node) {
+ const rightNode = node.init;
+ const sourceCode = context.getSourceCode();
+
+ return fixer.replaceText(
+ node,
+ `{${rightNode.property.name}} = ${sourceCode.getText(rightNode.object)}`
+ );
}
/**
@@ -155,13 +202,17 @@
if (isArrayIndexAccess(rightNode)) {
if (shouldCheck(reportNode.type, "array")) {
- report(reportNode, "array");
+ report(reportNode, "array", null);
}
return;
}
+ const fix = shouldFix(reportNode)
+ ? fixer => fixIntoObjectDestructuring(fixer, reportNode)
+ : null;
+
if (shouldCheck(reportNode.type, "object") && enforceForRenamedProperties) {
- report(reportNode, "object");
+ report(reportNode, "object", fix);
return;
}
@@ -172,7 +223,7 @@
(property.type === "Literal" && leftNode.name === property.value) ||
(property.type === "Identifier" && leftNode.name === property.name && !rightNode.computed)
) {
- report(reportNode, "object");
+ report(reportNode, "object", fix);
}
}
}

lib/rules/prefer-named-capture-group.js

@@ -0,0 +1,123 @@
+/**
+ * @fileoverview Rule to enforce requiring named capture groups in regular expression.
+ * @author Pig Fang <https://github.com/g-plane>
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const {
+ CALL,
+ CONSTRUCT,
+ ReferenceTracker,
+ getStringIfConstant
+} = require("eslint-utils");
+const regexpp = require("regexpp");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+const parser = new regexpp.RegExpParser();
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ type: "suggestion",
+
+ docs: {
+ description: "enforce using named capture group in regular expression",
+ category: "Best Practices",
+ recommended: false,
+ url: "https://eslint.org/docs/rules/prefer-named-capture-group"
+ },
+
+ schema: [],
+
+ messages: {
+ required: "Capture group '{{group}}' should be converted to a named or non-capturing group."
+ }
+ },
+
+ create(context) {
+
+ /**
+ * Function to check regular expression.
+ *
+ * @param {string} regex The regular expression to be check.
+ * @param {ASTNode} node AST node which contains regular expression.
+ * @param {boolean} uFlag Flag indicates whether unicode mode is enabled or not.
+ * @returns {void}
+ */
+ function checkRegex(regex, node, uFlag) {
+ let ast;
+
+ try {
+ ast = parser.parsePattern(regex, 0, regex.length, uFlag);
+ } catch (_) {
+
+ // ignore regex syntax errors
+ return;
+ }
+
+ regexpp.visitRegExpAST(ast, {
+ onCapturingGroupEnter(group) {
+ if (!group.name) {
+ const locNode = node.type === "Literal" ? node : node.arguments[0];
+
+ context.report({
+ node,
+ messageId: "required",
+ loc: {
+ start: {
+ line: locNode.loc.start.line,
+ column: locNode.loc.start.column + group.start + 1
+ },
+ end: {
+ line: locNode.loc.start.line,
+ column: locNode.loc.start.column + group.end + 1
+ }
+ },
+ data: {
+ group: group.raw
+ }
+ });
+ }
+ }
+ });
+ }
+
+ return {
+ Literal(node) {
+ if (node.regex) {
+ checkRegex(node.regex.pattern, node, node.regex.flags.includes("u"));
+ }
+ },
+ Program() {
+ const scope = context.getScope();
+ const tracker = new ReferenceTracker(scope);
+ const traceMap = {
+ RegExp: {
+ [CALL]: true,
+ [CONSTRUCT]: true
+ }
+ };
+
+ for (const { node } of tracker.iterateGlobalReferences(traceMap)) {
+ const regex = getStringIfConstant(node.arguments[0]);
+ const flags = getStringIfConstant(node.arguments[1]);
+
+ if (regex) {
+ checkRegex(regex, node, flags && flags.includes("u"));
+ }
+ }
+ }
+ };
+ }
+};

lib/rules/prefer-object-spread.js

@@ -14,7 +14,7 @@
isParenthesised
} = require("../util/ast-utils");
-const ANY_SPACE = /\s/;
+const ANY_SPACE = /\s/u;
/**
* Helper that checks if the Object.assign call has array spread

lib/rules/prefer-promise-reject-errors.js

@@ -27,7 +27,7 @@
{
type: "object",
properties: {
- allowEmptyReject: { type: "boolean" }
+ allowEmptyReject: { type: "boolean", default: false }
},
additionalProperties: false
}

lib/rules/prefer-spread.js

@@ -59,7 +59,7 @@
},
schema: [],
- fixable: "code"
+ fixable: null
},
create(context) {
@@ -78,18 +78,7 @@
if (isValidThisArg(expectedThis, thisArg, sourceCode)) {
context.report({
node,
- message: "Use the spread operator instead of '.apply()'.",
- fix(fixer) {
- if (expectedThis && expectedThis.type !== "Identifier") {
-
- // Don't fix cases where the `this` value could be a computed expression.
- return null;
- }
-
- const propertyDot = sourceCode.getFirstTokenBetween(applied, node.callee.property, token => token.value === ".");
-
- return fixer.replaceTextRange([propertyDot.range[0], node.range[1]], `(...${sourceCode.getText(node.arguments[1])})`);
- }
+ message: "Use the spread operator instead of '.apply()'."
});
}
}

lib/rules/prefer-template.js

@@ -52,7 +52,7 @@
return false;
}
- const match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-7]{1,3})/);
+ const match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-7]{1,3})/u);
if (match) {
@@ -187,14 +187,14 @@
* for some reason, don't add another backslash, because that would change the meaning of the code (it would cause
* an actual backslash character to appear before the dollar sign).
*/
- return `\`${currentNode.raw.slice(1, -1).replace(/\\*(\${|`)/g, matched => {
+ return `\`${currentNode.raw.slice(1, -1).replace(/\\*(\$\{|`)/gu, matched => {
if (matched.lastIndexOf("\\") % 2) {
return `\\${matched}`;
}
return matched;
// Unescape any quotes that appear in the original Literal that no longer need to be escaped.
- }).replace(new RegExp(`\\\\${currentNode.raw[0]}`, "g"), currentNode.raw[0])}\``;
+ }).replace(new RegExp(`\\\\${currentNode.raw[0]}`, "gu"), currentNode.raw[0])}\``;
}
if (currentNode.type === "TemplateLiteral") {

lib/rules/quotes.js

@@ -34,7 +34,7 @@
};
// An unescaped newline is a newline preceded by an even number of backslashes.
-const UNESCAPED_LINEBREAK_PATTERN = new RegExp(String.raw`(^|[^\\])(\\\\)*[${Array.from(astUtils.LINEBREAKS).join("")}]`);
+const UNESCAPED_LINEBREAK_PATTERN = new RegExp(String.raw`(^|[^\\])(\\\\)*[${Array.from(astUtils.LINEBREAKS).join("")}]`, "u");
/**
* Switches quoting of javascript string between ' " and `
@@ -54,7 +54,7 @@
if (newQuote === oldQuote) {
return str;
}
- return newQuote + str.slice(1, -1).replace(/\\(\${|\r\n?|\n|.)|["'`]|\${|(\r\n?|\n)/g, (match, escaped, newline) => {
+ return newQuote + str.slice(1, -1).replace(/\\(\$\{|\r\n?|\n|.)|["'`]|\$\{|(\r\n?|\n)/gu, (match, escaped, newline) => {
if (escaped === oldQuote || oldQuote === "`" && escaped === "${") {
return escaped; // unescape
}

lib/rules/require-jsdoc.js

@@ -23,22 +23,28 @@
type: "object",
properties: {
ClassDeclaration: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
MethodDefinition: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
FunctionDeclaration: {
- type: "boolean"
+ type: "boolean",
+ default: true
},
ArrowFunctionExpression: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
FunctionExpression: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
- additionalProperties: false
+ additionalProperties: false,
+ default: {}
}
},
additionalProperties: false
@@ -58,7 +64,7 @@
ArrowFunctionExpression: false,
FunctionExpression: false
};
- const options = Object.assign(DEFAULT_OPTIONS, context.options[0] && context.options[0].require || {});
+ const options = Object.assign(DEFAULT_OPTIONS, context.options[0] && context.options[0].require);
/**
* Report the error message

lib/rules/semi.js

@@ -72,11 +72,11 @@
create(context) {
- const OPT_OUT_PATTERN = /^[-[(/+`]/; // One of [(/+-`
+ const OPT_OUT_PATTERN = /^[-[(/+`]/u; // One of [(/+-`
const options = context.options[1];
const never = context.options[0] === "never";
const exceptOneLine = Boolean(options && options.omitLastInOneLineBlock);
- const beforeStatementContinuationChars = (options && options.beforeStatementContinuationChars) || "any";
+ const beforeStatementContinuationChars = options && options.beforeStatementContinuationChars || "any";
const sourceCode = context.getSourceCode();
//--------------------------------------------------------------------------
@@ -291,7 +291,7 @@
const parent = node.parent;
if ((parent.type !== "ForStatement" || parent.init !== node) &&
- (!/^For(?:In|Of)Statement/.test(parent.type) || parent.left !== node)
+ (!/^For(?:In|Of)Statement/u.test(parent.type) || parent.left !== node)
) {
checkForSemicolon(node);
}
@@ -318,7 +318,7 @@
}
},
ExportDefaultDeclaration(node) {
- if (!/(?:Class|Function)Declaration/.test(node.declaration.type)) {
+ if (!/(?:Class|Function)Declaration/u.test(node.declaration.type)) {
checkForSemicolon(node);
}
}

lib/rules/semi-spacing.js

@@ -29,10 +29,12 @@
type: "object",
properties: {
before: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
after: {
- type: "boolean"
+ type: "boolean",
+ default: true
}
},
additionalProperties: false
@@ -48,13 +50,9 @@
requireSpaceAfter = true;
if (typeof config === "object") {
- if (Object.prototype.hasOwnProperty.call(config, "before")) {
requireSpaceBefore = config.before;
- }
- if (Object.prototype.hasOwnProperty.call(config, "after")) {
requireSpaceAfter = config.after;
}
- }
/**
* Checks if a given token has leading whitespace.

lib/rules/sort-imports.js

@@ -25,7 +25,8 @@
type: "object",
properties: {
ignoreCase: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
memberSyntaxSortOrder: {
type: "array",
@@ -37,10 +38,12 @@
maxItems: 4
},
ignoreDeclarationSort: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
ignoreMemberSort: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/sort-keys.js

@@ -90,10 +90,12 @@
type: "object",
properties: {
caseSensitive: {
- type: "boolean"
+ type: "boolean",
+ default: true
},
natural: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false
@@ -106,8 +108,8 @@
// Parse options.
const order = context.options[0] || "asc";
const options = context.options[1];
- const insensitive = (options && options.caseSensitive) === false;
- const natual = Boolean(options && options.natural);
+ const insensitive = options && options.caseSensitive === false;
+ const natual = options && options.natural;
const isValidOrder = isValidOrders[
order + (insensitive ? "I" : "") + (natual ? "N" : "")
];
@@ -127,8 +129,14 @@
stack = stack.upper;
},
+ SpreadElement(node) {
+ if (node.parent.type === "ObjectExpression") {
+ stack.prevName = null;
+ }
+ },
+
Property(node) {
- if (node.parent.type === "ObjectPattern" || node.parent.properties.some(n => n.type === "SpreadElement")) {
+ if (node.parent.type === "ObjectPattern") {
return;
}

lib/rules/sort-vars.js

@@ -25,7 +25,8 @@
type: "object",
properties: {
ignoreCase: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/spaced-comment.js

@@ -126,7 +126,7 @@
pattern += "?"; // or nothing.
pattern += createExceptionsPattern(exceptions);
- return new RegExp(pattern);
+ return new RegExp(pattern); // eslint-disable-line require-unicode-regexp
}
/**
@@ -142,7 +142,7 @@
function createNeverStylePattern(markers) {
const pattern = `^(${markers.map(escape).join("|")})?[ \t]+`;
- return new RegExp(pattern);
+ return new RegExp(pattern); // eslint-disable-line require-unicode-regexp
}
//------------------------------------------------------------------------------
@@ -215,7 +215,8 @@
}
},
balanced: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false
@@ -249,9 +250,9 @@
// Create RegExp object for valid patterns.
rule[type] = {
beginRegex: requireSpace ? createAlwaysStylePattern(markers, exceptions) : createNeverStylePattern(markers),
- endRegex: balanced && requireSpace ? new RegExp(`${createExceptionsPattern(exceptions)}$`) : new RegExp(endNeverPattern),
+ endRegex: balanced && requireSpace ? new RegExp(`${createExceptionsPattern(exceptions)}$`) : new RegExp(endNeverPattern), // eslint-disable-line require-unicode-regexp
hasExceptions: exceptions.length > 0,
- markers: new RegExp(`^(${markers.map(escape).join("|")})`)
+ markers: new RegExp(`^(${markers.map(escape).join("|")})`) // eslint-disable-line require-unicode-regexp
};
return rule;

lib/rules/space-infix-ops.js

@@ -26,7 +26,8 @@
type: "object",
properties: {
int32Hint: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false

lib/rules/space-unary-ops.js

@@ -32,10 +32,12 @@
type: "object",
properties: {
words: {
- type: "boolean"
+ type: "boolean",
+ default: true
},
nonwords: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
overrides: {
type: "object",
@@ -46,11 +48,19 @@
},
additionalProperties: false
}
- ]
+ ],
+ messages: {
+ unexpectedBefore: "Unexpected space before unary operator '{{operator}}'.",
+ unexpectedAfter: "Unexpected space after unary operator '{{operator}}'.",
+ unexpectedAfterWord: "Unexpected space after unary word operator '{{word}}'.",
+ wordOperator: "Unary word operator '{{word}}' must be followed by whitespace.",
+ operator: "Unary operator '{{operator}}' must be followed by whitespace.",
+ beforeUnaryExpressions: "Space is required before unary expressions '{{token}}'."
+ }
},
create(context) {
- const options = context.options && Array.isArray(context.options) && context.options[0] || { words: true, nonwords: false };
+ const options = context.options[0] || { words: true, nonwords: false };
const sourceCode = context.getSourceCode();
@@ -98,7 +108,7 @@
if (secondToken.range[0] === firstToken.range[1]) {
context.report({
node,
- message: "Unary word operator '{{word}}' must be followed by whitespace.",
+ messageId: "wordOperator",
data: {
word
},
@@ -122,7 +132,7 @@
if (secondToken.range[0] > firstToken.range[1]) {
context.report({
node,
- message: "Unexpected space after unary word operator '{{word}}'.",
+ messageId: "unexpectedAfterWord",
data: {
word
},
@@ -198,7 +208,7 @@
if (firstToken.range[1] === secondToken.range[0]) {
context.report({
node,
- message: "Unary operator '{{operator}}' must be followed by whitespace.",
+ messageId: "operator",
data: {
operator: firstToken.value
},
@@ -211,7 +221,7 @@
if (firstToken.range[1] === secondToken.range[0]) {
context.report({
node,
- message: "Space is required before unary expressions '{{token}}'.",
+ messageId: "beforeUnaryExpressions",
data: {
token: secondToken.value
},
@@ -235,7 +245,7 @@
if (secondToken.range[0] > firstToken.range[1]) {
context.report({
node,
- message: "Unexpected space after unary operator '{{operator}}'.",
+ messageId: "unexpectedAfter",
data: {
operator: firstToken.value
},
@@ -251,7 +261,7 @@
if (secondToken.range[0] > firstToken.range[1]) {
context.report({
node,
- message: "Unexpected space before unary operator '{{operator}}'.",
+ messageId: "unexpectedBefore",
data: {
operator: secondToken.value
},

lib/rules/strict.js

@@ -15,19 +15,6 @@
// Helpers
//------------------------------------------------------------------------------
-const messages = {
- function: "Use the function form of 'use strict'.",
- global: "Use the global form of 'use strict'.",
- multiple: "Multiple 'use strict' directives.",
- never: "Strict mode is not permitted.",
- unnecessary: "Unnecessary 'use strict' directive.",
- module: "'use strict' is unnecessary inside of modules.",
- implied: "'use strict' is unnecessary when implied strict mode is enabled.",
- unnecessaryInClasses: "'use strict' is unnecessary inside of classes.",
- nonSimpleParameterList: "'use strict' directive inside a function with non-simple parameter list throws a syntax error since ES2016.",
- wrap: "Wrap {{name}} in a function with 'use strict' directive."
-};
-
/**
* Gets all of the Use Strict Directives in the Directive Prologue of a group of
* statements.
@@ -95,7 +82,19 @@
}
],
- fixable: "code"
+ fixable: "code",
+ messages: {
+ function: "Use the function form of 'use strict'.",
+ global: "Use the global form of 'use strict'.",
+ multiple: "Multiple 'use strict' directives.",
+ never: "Strict mode is not permitted.",
+ unnecessary: "Unnecessary 'use strict' directive.",
+ module: "'use strict' is unnecessary inside of modules.",
+ implied: "'use strict' is unnecessary when implied strict mode is enabled.",
+ unnecessaryInClasses: "'use strict' is unnecessary inside of classes.",
+ nonSimpleParameterList: "'use strict' directive inside a function with non-simple parameter list throws a syntax error since ES2016.",
+ wrap: "Wrap {{name}} in a function with 'use strict' directive."
+ }
},
create(context) {
@@ -134,36 +133,36 @@
* @param {ASTNode[]} nodes Nodes.
* @param {string} start Index to start from.
* @param {string} end Index to end before.
- * @param {string} message Message to display.
+ * @param {string} messageId Message to display.
* @param {boolean} fix `true` if the directive should be fixed (i.e. removed)
* @returns {void}
*/
- function reportSlice(nodes, start, end, message, fix) {
+ function reportSlice(nodes, start, end, messageId, fix) {
nodes.slice(start, end).forEach(node => {
- context.report({ node, message, fix: fix ? getFixFunction(node) : null });
+ context.report({ node, messageId, fix: fix ? getFixFunction(node) : null });
});
}
/**
* Report all nodes in an array with a given message.
* @param {ASTNode[]} nodes Nodes.
- * @param {string} message Message to display.
+ * @param {string} messageId Message id to display.
* @param {boolean} fix `true` if the directive should be fixed (i.e. removed)
* @returns {void}
*/
- function reportAll(nodes, message, fix) {
- reportSlice(nodes, 0, nodes.length, message, fix);
+ function reportAll(nodes, messageId, fix) {
+ reportSlice(nodes, 0, nodes.length, messageId, fix);
}
/**
* Report all nodes in an array, except the first, with a given message.
* @param {ASTNode[]} nodes Nodes.
- * @param {string} message Message to display.
+ * @param {string} messageId Message id to display.
* @param {boolean} fix `true` if the directive should be fixed (i.e. removed)
* @returns {void}
*/
- function reportAllExceptFirst(nodes, message, fix) {
- reportSlice(nodes, 1, nodes.length, message, fix);
+ function reportAllExceptFirst(nodes, messageId, fix) {
+ reportSlice(nodes, 1, nodes.length, messageId, fix);
}
/**
@@ -181,21 +180,21 @@
if (isStrict) {
if (!isSimpleParameterList(node.params)) {
- context.report({ node: useStrictDirectives[0], message: messages.nonSimpleParameterList });
+ context.report({ node: useStrictDirectives[0], messageId: "nonSimpleParameterList" });
} else if (isParentStrict) {
- context.report({ node: useStrictDirectives[0], message: messages.unnecessary, fix: getFixFunction(useStrictDirectives[0]) });
+ context.report({ node: useStrictDirectives[0], messageId: "unnecessary", fix: getFixFunction(useStrictDirectives[0]) });
} else if (isInClass) {
- context.report({ node: useStrictDirectives[0], message: messages.unnecessaryInClasses, fix: getFixFunction(useStrictDirectives[0]) });
+ context.report({ node: useStrictDirectives[0], messageId: "unnecessaryInClasses", fix: getFixFunction(useStrictDirectives[0]) });
}
- reportAllExceptFirst(useStrictDirectives, messages.multiple, true);
+ reportAllExceptFirst(useStrictDirectives, "multiple", true);
} else if (isParentGlobal) {
if (isSimpleParameterList(node.params)) {
- context.report({ node, message: messages.function });
+ context.report({ node, messageId: "function" });
} else {
context.report({
node,
- message: messages.wrap,
+ messageId: "wrap",
data: { name: astUtils.getFunctionNameWithKind(node) }
});
}
@@ -228,10 +227,10 @@
enterFunctionInFunctionMode(node, useStrictDirectives);
} else if (useStrictDirectives.length > 0) {
if (isSimpleParameterList(node.params)) {
- reportAll(useStrictDirectives, messages[mode], shouldFix(mode));
+ reportAll(useStrictDirectives, mode, shouldFix(mode));
} else {
- context.report({ node: useStrictDirectives[0], message: messages.nonSimpleParameterList });
- reportAllExceptFirst(useStrictDirectives, messages.multiple, true);
+ context.report({ node: useStrictDirectives[0], messageId: "nonSimpleParameterList" });
+ reportAllExceptFirst(useStrictDirectives, "multiple", true);
}
}
}
@@ -246,11 +245,11 @@
if (mode === "global") {
if (node.body.length > 0 && useStrictDirectives.length === 0) {
- context.report({ node, message: messages.global });
+ context.report({ node, messageId: "global" });
}
- reportAllExceptFirst(useStrictDirectives, messages.multiple, true);
+ reportAllExceptFirst(useStrictDirectives, "multiple", true);
} else {
- reportAll(useStrictDirectives, messages[mode], shouldFix(mode));
+ reportAll(useStrictDirectives, mode, shouldFix(mode));
}
},
FunctionDeclaration: enterFunction,

lib/rules/switch-colon-spacing.js

@@ -30,14 +30,19 @@
{
type: "object",
properties: {
- before: { type: "boolean" },
- after: { type: "boolean" }
+ before: { type: "boolean", default: false },
+ after: { type: "boolean", default: true }
},
additionalProperties: false
}
],
-
- fixable: "whitespace"
+ fixable: "whitespace",
+ messages: {
+ expectedBefore: "Expected space(s) before this colon.",
+ expectedAfter: "Expected space(s) after this colon.",
+ unexpectedBefore: "Unexpected space(s) before this colon.",
+ unexpectedAfter: "Unexpected space(s) after this colon."
+ }
},
create(context) {
@@ -118,8 +123,7 @@
context.report({
node,
loc: colonToken.loc,
- message: "{{verb}} space(s) before this colon.",
- data: { verb: beforeSpacing ? "Expected" : "Unexpected" },
+ messageId: beforeSpacing ? "expectedBefore" : "unexpectedBefore",
fix: fixer => fix(fixer, beforeToken, colonToken, beforeSpacing)
});
}
@@ -127,8 +131,7 @@
context.report({
node,
loc: colonToken.loc,
- message: "{{verb}} space(s) after this colon.",
- data: { verb: afterSpacing ? "Expected" : "Unexpected" },
+ messageId: afterSpacing ? "expectedAfter" : "unexpectedAfter",
fix: fixer => fix(fixer, colonToken, afterToken, afterSpacing)
});
}

lib/rules/symbol-description.js

@@ -26,8 +26,11 @@
recommended: false,
url: "https://eslint.org/docs/rules/symbol-description"
},
-
- schema: []
+ fixable: null,
+ schema: [],
+ messages: {
+ expected: "Expected Symbol to have a description."
+ }
},
create(context) {
@@ -43,7 +46,7 @@
if (node.arguments.length === 0) {
context.report({
node,
- message: "Expected Symbol to have a description."
+ messageId: "expected"
});
}
}

lib/rules/template-curly-spacing.js

@@ -15,8 +15,8 @@
// Helpers
//------------------------------------------------------------------------------
-const OPEN_PAREN = /\$\{$/;
-const CLOSE_PAREN = /^\}/;
+const OPEN_PAREN = /\$\{$/u;
+const CLOSE_PAREN = /^\}/u;
//------------------------------------------------------------------------------
// Rule Definition
@@ -37,13 +37,19 @@
schema: [
{ enum: ["always", "never"] }
- ]
+ ],
+ messages: {
+ expectedBefore: "Expected space(s) before '}'.",
+ expectedAfter: "Expected space(s) after '${'.",
+ unexpectedBefore: "Unexpected space(s) before '}'.",
+ unexpectedAfter: "Unexpected space(s) after '${'."
+ }
},
create(context) {
const sourceCode = context.getSourceCode();
const always = context.options[0] === "always";
- const prefix = always ? "Expected" : "Unexpected";
+ const prefix = always ? "expected" : "unexpected";
/**
* Checks spacing before `}` of a given token.
@@ -60,10 +66,7 @@
) {
context.report({
loc: token.loc.start,
- message: "{{prefix}} space(s) before '}'.",
- data: {
- prefix
- },
+ messageId: `${prefix}Before`,
fix(fixer) {
if (always) {
return fixer.insertTextBefore(token, " ");
@@ -95,10 +98,7 @@
line: token.loc.end.line,
column: token.loc.end.column - 2
},
- message: "{{prefix}} space(s) after '${'.",
- data: {
- prefix
- },
+ messageId: `${prefix}After`,
fix(fixer) {
if (always) {
return fixer.insertTextAfter(token, " ");

lib/rules/template-tag-spacing.js

@@ -24,7 +24,11 @@
schema: [
{ enum: ["always", "never"] }
- ]
+ ],
+ messages: {
+ unexpected: "Unexpected space between template tag and template literal.",
+ missing: "Missing space between template tag and template literal."
+ }
},
create(context) {
@@ -46,7 +50,7 @@
context.report({
node,
loc: tagToken.loc.start,
- message: "Unexpected space between template tag and template literal.",
+ messageId: "unexpected",
fix(fixer) {
const comments = sourceCode.getCommentsBefore(node.quasi);
@@ -65,7 +69,7 @@
context.report({
node,
loc: tagToken.loc.start,
- message: "Missing space between template tag and template literal.",
+ messageId: "missing",
fix(fixer) {
return fixer.insertTextAfter(tagToken, " ");
}

lib/rules/unicode-bom.js

@@ -25,7 +25,11 @@
{
enum: ["always", "never"]
}
- ]
+ ],
+ messages: {
+ expected: "Expected Unicode BOM (Byte Order Mark).",
+ unexpected: "Unexpected Unicode BOM (Byte Order Mark)."
+ }
},
create(context) {
@@ -46,7 +50,7 @@
context.report({
node,
loc: location,
- message: "Expected Unicode BOM (Byte Order Mark).",
+ messageId: "expected",
fix(fixer) {
return fixer.insertTextBeforeRange([0, 1], "\uFEFF");
}
@@ -55,7 +59,7 @@
context.report({
node,
loc: location,
- message: "Unexpected Unicode BOM (Byte Order Mark).",
+ messageId: "unexpected",
fix(fixer) {
return fixer.removeRange([-1, 0]);
}

lib/rules/use-isnan.js

@@ -20,15 +20,18 @@
url: "https://eslint.org/docs/rules/use-isnan"
},
- schema: []
+ schema: [],
+ messages: {
+ useIsNaN: "Use the isNaN function to compare with NaN."
+ }
},
create(context) {
return {
BinaryExpression(node) {
- if (/^(?:[<>]|[!=]=)=?$/.test(node.operator) && (node.left.name === "NaN" || node.right.name === "NaN")) {
- context.report({ node, message: "Use the isNaN function to compare with NaN." });
+ if (/^(?:[<>]|[!=]=)=?$/u.test(node.operator) && (node.left.name === "NaN" || node.right.name === "NaN")) {
+ context.report({ node, messageId: "useIsNaN" });
}
}
};

lib/rules/valid-jsdoc.js

@@ -42,22 +42,27 @@
}
},
requireReturn: {
- type: "boolean"
+ type: "boolean",
+ default: true
},
requireParamDescription: {
- type: "boolean"
+ type: "boolean",
+ default: true
},
requireReturnDescription: {
- type: "boolean"
+ type: "boolean",
+ default: true
},
matchDescription: {
type: "string"
},
requireReturnType: {
- type: "boolean"
+ type: "boolean",
+ default: true
},
requireParamType: {
- type: "boolean"
+ type: "boolean",
+ default: true
}
},
additionalProperties: false
@@ -65,6 +70,22 @@
],
fixable: "code",
+ messages: {
+ unexpectedTag: "Unexpected @{{title}} tag; function has no return statement.",
+ expected: "Expected JSDoc for '{{name}}' but found '{{jsdocName}}'.",
+ use: "Use @{{name}} instead.",
+ useType: "Use '{{expectedTypeName}}' instead of '{{currentTypeName}}'.",
+ syntaxError: "JSDoc syntax error.",
+ missingBrace: "JSDoc type missing brace.",
+ missingParamDesc: "Missing JSDoc parameter description for '{{name}}'.",
+ missingParamType: "Missing JSDoc parameter type for '{{name}}'.",
+ missingReturnType: "Missing JSDoc return type.",
+ missingReturnDesc: "Missing JSDoc return description.",
+ missingReturn: "Missing JSDoc @{{returns}} for function.",
+ missingParam: "Missing JSDoc for parameter '{{name}}'.",
+ duplicateParam: "Duplicate JSDoc parameter '{{name}}'.",
+ unsatisfiedDesc: "JSDoc description does not satisfy the regex pattern."
+ },
deprecated: true,
replacedBy: []
@@ -231,7 +252,7 @@
typeToCheck.expectedTypeName !== typeToCheck.currentType.name) {
context.report({
node: jsdocNode,
- message: "Use '{{expectedTypeName}}' instead of '{{currentTypeName}}'.",
+ messageId: "useType",
loc: getAbsoluteRange(jsdocNode, typeToCheck.currentType),
data: {
currentTypeName: typeToCheck.currentType.name,
@@ -279,10 +300,10 @@
});
} catch (ex) {
- if (/braces/i.test(ex.message)) {
- context.report({ node: jsdocNode, message: "JSDoc type missing brace." });
+ if (/braces/iu.test(ex.message)) {
+ context.report({ node: jsdocNode, messageId: "missingBrace" });
} else {
- context.report({ node: jsdocNode, message: "JSDoc syntax error." });
+ context.report({ node: jsdocNode, messageId: "syntaxError" });
}
return;
@@ -332,7 +353,7 @@
context.report({
node: jsdocNode,
- message: "Use @{{name}} instead.",
+ messageId: "use",
loc: {
start: entireTagRange.start,
end: {
@@ -363,7 +384,7 @@
if (requireParamType && !param.type) {
context.report({
node: jsdocNode,
- message: "Missing JSDoc parameter type for '{{name}}'.",
+ messageId: "missingParamType",
loc: getAbsoluteRange(jsdocNode, param),
data: { name: param.name }
});
@@ -371,7 +392,7 @@
if (!param.description && requireParamDescription) {
context.report({
node: jsdocNode,
- message: "Missing JSDoc parameter description for '{{name}}'.",
+ messageId: "missingParamDesc",
loc: getAbsoluteRange(jsdocNode, param),
data: { name: param.name }
});
@@ -379,7 +400,7 @@
if (paramTagsByName[param.name]) {
context.report({
node: jsdocNode,
- message: "Duplicate JSDoc parameter '{{name}}'.",
+ messageId: "duplicateParam",
loc: getAbsoluteRange(jsdocNode, param),
data: { name: param.name }
});
@@ -392,7 +413,7 @@
if (!requireReturn && !functionData.returnPresent && (returnsTag.type === null || !isValidReturnType(returnsTag)) && !isAbstract) {
context.report({
node: jsdocNode,
- message: "Unexpected @{{title}} tag; function has no return statement.",
+ messageId: "unexpectedTag",
loc: getAbsoluteRange(jsdocNode, returnsTag),
data: {
title: returnsTag.title
@@ -400,11 +421,11 @@
});
} else {
if (requireReturnType && !returnsTag.type) {
- context.report({ node: jsdocNode, message: "Missing JSDoc return type." });
+ context.report({ node: jsdocNode, messageId: "missingReturnType" });
}
if (!isValidReturnType(returnsTag) && !returnsTag.description && requireReturnDescription) {
- context.report({ node: jsdocNode, message: "Missing JSDoc return description." });
+ context.report({ node: jsdocNode, messageId: "missingReturnDesc" });
}
}
}
@@ -416,7 +437,7 @@
if (requireReturn || (functionData.returnPresent && !node.async)) {
context.report({
node: jsdocNode,
- message: "Missing JSDoc @{{returns}} for function.",
+ messageId: "missingReturn",
data: {
returns: prefer.returns || "returns"
}
@@ -440,7 +461,7 @@
if (jsdocParamNames[paramsIndex] && (name !== jsdocParamNames[paramsIndex])) {
context.report({
node: jsdocNode,
- message: "Expected JSDoc for '{{name}}' but found '{{jsdocName}}'.",
+ messageId: "expected",
loc: getAbsoluteRange(jsdocNode, paramTagsByName[jsdocParamNames[paramsIndex]]),
data: {
name,
@@ -450,7 +471,7 @@
} else if (!paramTagsByName[name] && !isOverride) {
context.report({
node: jsdocNode,
- message: "Missing JSDoc for parameter '{{name}}'.",
+ messageId: "missingParam",
data: {
name
}
@@ -461,10 +482,10 @@
}
if (options.matchDescription) {
- const regex = new RegExp(options.matchDescription);
+ const regex = new RegExp(options.matchDescription); // eslint-disable-line require-unicode-regexp
if (!regex.test(jsdoc.description)) {
- context.report({ node: jsdocNode, message: "JSDoc description does not satisfy the regex pattern." });
+ context.report({ node: jsdocNode, messageId: "unsatisfiedDesc" });
}
}

lib/rules/valid-typeof.js

@@ -24,12 +24,17 @@
type: "object",
properties: {
requireStringLiterals: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false
}
- ]
+ ],
+ messages: {
+ invalidValue: "Invalid typeof comparison value.",
+ notString: "Typeof comparisons should be to string literals."
+ }
},
create(context) {
@@ -65,10 +70,10 @@
const value = sibling.type === "Literal" ? sibling.value : sibling.quasis[0].value.cooked;
if (VALID_TYPES.indexOf(value) === -1) {
- context.report({ node: sibling, message: "Invalid typeof comparison value." });
+ context.report({ node: sibling, messageId: "invalidValue" });
}
} else if (requireStringLiterals && !isTypeofExpression(sibling)) {
- context.report({ node: sibling, message: "Typeof comparisons should be to string literals." });
+ context.report({ node: sibling, messageId: "notString" });
}
}
}

lib/rules/vars-on-top.js

@@ -20,11 +20,13 @@
url: "https://eslint.org/docs/rules/vars-on-top"
},
- schema: []
+ schema: [],
+ messages: {
+ top: "All 'var' declarations must be at the top of the function scope."
+ }
},
create(context) {
- const errorMessage = "All 'var' declarations must be at the top of the function scope.";
//--------------------------------------------------------------------------
// Helpers
@@ -103,7 +105,7 @@
*/
function globalVarCheck(node, parent) {
if (!isVarOnTop(node, parent.body)) {
- context.report({ node, message: errorMessage });
+ context.report({ node, messageId: "top" });
}
}
@@ -115,10 +117,10 @@
* @returns {void}
*/
function blockScopeVarCheck(node, parent, grandParent) {
- if (!(/Function/.test(grandParent.type) &&
+ if (!(/Function/u.test(grandParent.type) &&
parent.type === "BlockStatement" &&
isVarOnTop(node, parent.body))) {
- context.report({ node, message: errorMessage });
+ context.report({ node, messageId: "top" });
}
}

lib/rules/wrap-iife.js

@@ -34,20 +34,26 @@
type: "object",
properties: {
functionPrototypeMethods: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false
}
],
- fixable: "code"
+ fixable: "code",
+ messages: {
+ wrapInvocation: "Wrap an immediate function invocation in parentheses.",
+ wrapExpression: "Wrap only the function expression in parens.",
+ moveInvocation: "Move the invocation into the parens that contain the function."
+ }
},
create(context) {
const style = context.options[0] || "outside";
- const includeFunctionPrototypeMethods = (context.options[1] && context.options[1].functionPrototypeMethods) || false;
+ const includeFunctionPrototypeMethods = context.options[1] && context.options[1].functionPrototypeMethods;
const sourceCode = context.getSourceCode();
@@ -99,7 +105,7 @@
if (!callExpressionWrapped && !functionExpressionWrapped) {
context.report({
node,
- message: "Wrap an immediate function invocation in parentheses.",
+ messageId: "wrapInvocation",
fix(fixer) {
const nodeToSurround = style === "inside" ? innerNode : node;
@@ -109,7 +115,7 @@
} else if (style === "inside" && !functionExpressionWrapped) {
context.report({
node,
- message: "Wrap only the function expression in parens.",
+ messageId: "wrapExpression",
fix(fixer) {
/*
@@ -129,7 +135,7 @@
} else if (style === "outside" && !callExpressionWrapped) {
context.report({
node,
- message: "Move the invocation into the parens that contain the function.",
+ messageId: "moveInvocation",
fix(fixer) {
/*

lib/rules/yield-star-spacing.js

@@ -38,7 +38,13 @@
}
]
}
- ]
+ ],
+ messages: {
+ missingBefore: "Missing space before *.",
+ missingAfter: "Missing space after *.",
+ unexpectedBefore: "Unexpected space before *.",
+ unexpectedAfter: "Unexpected space after *."
+ }
},
create(context) {
@@ -70,16 +76,17 @@
const after = leftToken.value === "*";
const spaceRequired = mode[side];
const node = after ? leftToken : rightToken;
- const type = spaceRequired ? "Missing" : "Unexpected";
- const message = "{{type}} space {{side}} *.";
+ let messageId = "";
+
+ if (spaceRequired) {
+ messageId = side === "before" ? "missingBefore" : "missingAfter";
+ } else {
+ messageId = side === "before" ? "unexpectedBefore" : "unexpectedAfter";
+ }
context.report({
node,
- message,
- data: {
- type,
- side
- },
+ messageId,
fix(fixer) {
if (spaceRequired) {
if (after) {

lib/rules/yoda.js

@@ -20,7 +20,7 @@
* @returns {boolean} Whether or not it is a comparison operator.
*/
function isComparisonOperator(operator) {
- return (/^(==|===|!=|!==|<|>|<=|>=)$/).test(operator);
+ return (/^(==|===|!=|!==|<|>|<=|>=)$/u).test(operator);
}
/**
@@ -29,7 +29,7 @@
* @returns {boolean} Whether or not it is an equality operator.
*/
function isEqualityOperator(operator) {
- return (/^(==|===)$/).test(operator);
+ return (/^(==|===)$/u).test(operator);
}
/**
@@ -169,17 +169,22 @@
type: "object",
properties: {
exceptRange: {
- type: "boolean"
+ type: "boolean",
+ default: false
},
onlyEquality: {
- type: "boolean"
+ type: "boolean",
+ default: false
}
},
additionalProperties: false
}
],
- fixable: "code"
+ fixable: "code",
+ messages: {
+ expected: "Expected literal to be on the {{expectedSide}} side of {{operator}}."
+ }
},
create(context) {
@@ -297,7 +302,7 @@
) {
context.report({
node,
- message: "Expected literal to be on the {{expectedSide}} side of {{operator}}.",
+ messageId: "expected",
data: {
operator: node.operator,
expectedSide: always ? "left" : "right"

lib/rules.js

@@ -10,8 +10,8 @@
//------------------------------------------------------------------------------
const lodash = require("lodash");
-const loadRules = require("./load-rules");
const ruleReplacements = require("../conf/replacements").rules;
+const builtInRules = require("./built-in-rules-index");
//------------------------------------------------------------------------------
// Helpers
@@ -59,8 +59,9 @@
class Rules {
constructor() {
this._rules = Object.create(null);
-
- this.load();
+ Object.keys(builtInRules).forEach(ruleId => {
+ this.define(ruleId, builtInRules[ruleId]);
+ });
}
/**
@@ -74,37 +75,6 @@
}
/**
- * Loads and registers all rules from passed rules directory.
- * @param {string} [rulesDir] Path to rules directory, may be relative. Defaults to `lib/rules`.
- * @param {string} cwd Current working directory
- * @returns {void}
- */
- load(rulesDir, cwd) {
- const newRules = loadRules(rulesDir, cwd);
-
- Object.keys(newRules).forEach(ruleId => {
- this.define(ruleId, newRules[ruleId]);
- });
- }
-
- /**
- * Registers all given rules of a plugin.
- * @param {Object} plugin The plugin object to import.
- * @param {string} pluginName The name of the plugin without prefix (`eslint-plugin-`).
- * @returns {void}
- */
- importPlugin(plugin, pluginName) {
- if (plugin.rules) {
- Object.keys(plugin.rules).forEach(ruleId => {
- const qualifiedRuleId = `${pluginName}/${ruleId}`,
- rule = plugin.rules[ruleId];
-
- this.define(qualifiedRuleId, rule);
- });
- }
- }
-
- /**
* Access rule handler by id (file name).
* @param {string} ruleId Rule id (file name).
* @returns {{create: Function, schema: JsonSchema[]}}

lib/testers/rule-tester.js

@@ -379,7 +379,7 @@
}
}
- validator.validate(config, "rule-tester", ruleMap.get.bind(ruleMap), new Environments());
+ validator.validate(config, ruleMap.get.bind(ruleMap), new Environments(), "rule-tester");
return {
messages: linter.verify(code, config, filename, true),

lib/util/ajv.js

@@ -17,6 +17,7 @@
const ajv = new Ajv({
meta: false,
+ useDefaults: true,
validateSchema: false,
missingRefs: "ignore",
verbose: true,

lib/util/ast-utils.js

@@ -16,19 +16,19 @@
// Helpers
//------------------------------------------------------------------------------
-const anyFunctionPattern = /^(?:Function(?:Declaration|Expression)|ArrowFunctionExpression)$/;
-const anyLoopPattern = /^(?:DoWhile|For|ForIn|ForOf|While)Statement$/;
-const arrayOrTypedArrayPattern = /Array$/;
-const arrayMethodPattern = /^(?:every|filter|find|findIndex|forEach|map|some)$/;
-const bindOrCallOrApplyPattern = /^(?:bind|call|apply)$/;
-const breakableTypePattern = /^(?:(?:Do)?While|For(?:In|Of)?|Switch)Statement$/;
-const thisTagPattern = /^[\s*]*@this/m;
+const anyFunctionPattern = /^(?:Function(?:Declaration|Expression)|ArrowFunctionExpression)$/u;
+const anyLoopPattern = /^(?:DoWhile|For|ForIn|ForOf|While)Statement$/u;
+const arrayOrTypedArrayPattern = /Array$/u;
+const arrayMethodPattern = /^(?:every|filter|find|findIndex|forEach|map|some)$/u;
+const bindOrCallOrApplyPattern = /^(?:bind|call|apply)$/u;
+const breakableTypePattern = /^(?:(?:Do)?While|For(?:In|Of)?|Switch)Statement$/u;
+const thisTagPattern = /^[\s*]*@this/mu;
-const COMMENTS_IGNORE_PATTERN = /^\s*(?:eslint|jshint\s+|jslint\s+|istanbul\s+|globals?\s+|exported\s+|jscs)/;
+const COMMENTS_IGNORE_PATTERN = /^\s*(?:eslint|jshint\s+|jslint\s+|istanbul\s+|globals?\s+|exported\s+|jscs)/u;
const LINEBREAKS = new Set(["\r\n", "\r", "\n", "\u2028", "\u2029"]);
-const LINEBREAK_MATCHER = /\r\n|[\r\n\u2028\u2029]/;
-const SHEBANG_MATCHER = /^#!([^\r\n]+)/;
+const LINEBREAK_MATCHER = /\r\n|[\r\n\u2028\u2029]/u;
+const SHEBANG_MATCHER = /^#!([^\r\n]+)/u;
// A set of node types that can contain a list of statements
const STATEMENT_LIST_PARENTS = new Set(["Program", "BlockStatement", "SwitchCase"]);
@@ -398,7 +398,7 @@
* @returns {RegExp} A global regular expression that matches line terminators
*/
function createGlobalLinebreakMatcher() {
- return new RegExp(LINEBREAK_MATCHER.source, "g");
+ return new RegExp(LINEBREAK_MATCHER.source, "gu");
}
/**
@@ -1006,7 +1006,7 @@
* '5' // false
*/
isDecimalInteger(node) {
- return node.type === "Literal" && typeof node.value === "number" && /^(0|[1-9]\d*)$/.test(node.raw);
+ return node.type === "Literal" && typeof node.value === "number" && /^(0|[1-9]\d*)$/u.test(node.raw);
},
/**

lib/util/config-comment-parser.js

@@ -26,32 +26,29 @@
module.exports = class ConfigCommentParser {
/**
- * Parses a list of "name:boolean_value" or/and "name" options divided by comma or
+ * Parses a list of "name:string_value" or/and "name" options divided by comma or
* whitespace. Used for "global" and "exported" comments.
* @param {string} string The string to parse.
* @param {Comment} comment The comment node which has the string.
- * @returns {Object} Result map object of names and boolean values
+ * @returns {Object} Result map object of names and string values, or null values if no value was provided
*/
- parseBooleanConfig(string, comment) {
- debug("Parsing Boolean config");
+ parseStringConfig(string, comment) {
+ debug("Parsing String config");
const items = {};
// Collapse whitespace around `:` and `,` to make parsing easier
- const trimmedString = string.replace(/\s*([:,])\s*/g, "$1");
+ const trimmedString = string.replace(/\s*([:,])\s*/gu, "$1");
- trimmedString.split(/\s|,+/).forEach(name => {
+ trimmedString.split(/\s|,+/u).forEach(name => {
if (!name) {
return;
}
- // value defaults to "false" (if not provided), e.g: "foo" => ["foo", "false"]
- const [key, value = "false"] = name.split(":");
+ // value defaults to null (if not provided), e.g: "foo" => ["foo", null]
+ const [key, value = null] = name.split(":");
- items[key] = {
- value: value === "true",
- comment
- };
+ items[key] = { value, comment };
});
return items;
}
@@ -93,7 +90,7 @@
* But we are supporting that. So this is a fallback for that.
*/
items = {};
- const normalizedString = string.replace(/([a-zA-Z0-9\-/]+):/g, "\"$1\":").replace(/(]|[0-9])\s+(?=")/, "$1,");
+ const normalizedString = string.replace(/([a-zA-Z0-9\-/]+):/gu, "\"$1\":").replace(/(\]|[0-9])\s+(?=")/u, "$1,");
try {
items = JSON.parse(`{${normalizedString}}`);
@@ -131,7 +128,7 @@
const items = {};
// Collapse whitespace around commas
- string.replace(/\s*,\s*/g, ",").split(/,+/).forEach(name => {
+ string.replace(/\s*,\s*/gu, ",").split(/,+/u).forEach(name => {
const trimmedName = name.trim();
if (trimmedName) {

lib/util/glob-utils.js

@@ -52,7 +52,7 @@
const cwd = (options && options.cwd) || process.cwd();
let extensions = (options && options.extensions) || [".js"];
- extensions = extensions.map(ext => ext.replace(/^\./, ""));
+ extensions = extensions.map(ext => ext.replace(/^\./u, ""));
let suffix = "/**";
@@ -70,11 +70,15 @@
* @private
*/
return function(pathname) {
+ if (pathname === "") {
+ return "";
+ }
+
let newPath = pathname;
const resolvedPath = path.resolve(cwd, pathname);
if (directoryExists(resolvedPath)) {
- newPath = pathname.replace(/[/\\]$/, "") + suffix;
+ newPath = pathname.replace(/[/\\]$/u, "") + suffix;
}
return pathUtils.convertPathToPosix(newPath);
@@ -169,7 +173,7 @@
return patterns.map(processPathExtensions);
}
-const dotfilesPattern = /(?:(?:^\.)|(?:[/\\]\.))[^/\\.].*/;
+const dotfilesPattern = /(?:(?:^\.)|(?:[/\\]\.))[^/\\.].*/u;
/**
* Build a list of absolute filesnames on which ESLint will act.
@@ -201,6 +205,13 @@
debug("Creating list of files to process.");
const resolvedPathsByGlobPattern = resolvedGlobPatterns.map(pattern => {
+ if (pattern === "") {
+ return [{
+ filename: "",
+ behavior: SILENTLY_IGNORE
+ }];
+ }
+
const file = path.resolve(cwd, pattern);
if (options.globInputPaths === false || (fs.existsSync(file) && fs.statSync(file).isFile())) {
@@ -240,7 +251,7 @@
});
const allPathDescriptors = resolvedPathsByGlobPattern.reduce((pathsForAllGlobs, pathsForCurrentGlob, index) => {
- if (pathsForCurrentGlob.every(pathDescriptor => pathDescriptor.behavior === SILENTLY_IGNORE)) {
+ if (pathsForCurrentGlob.every(pathDescriptor => pathDescriptor.behavior === SILENTLY_IGNORE && pathDescriptor.filename !== "")) {
throw new (pathsForCurrentGlob.length ? AllFilesIgnoredError : NoFilesFoundError)(globPatterns[index]);
}

lib/util/ignored-paths.js

@@ -89,7 +89,7 @@
*/
const normalizePathSeps = path.sep === "/"
? (str => str)
- : ((seps, str) => str.replace(seps, "/")).bind(null, new RegExp(`\\${path.sep}`, "g"));
+ : ((seps, str) => str.replace(seps, "/")).bind(null, new RegExp(`\\${path.sep}`, "gu"));
/* eslint-enable valid-jsdoc */
/**
@@ -104,7 +104,7 @@
}
const prefix = globPattern.startsWith("!") ? "!" : "";
- const globWithoutPrefix = globPattern.replace(/^!/, "");
+ const globWithoutPrefix = globPattern.replace(/^!/u, "");
if (globWithoutPrefix.startsWith("/")) {
return `${prefix}/${normalizePathSeps(relativePathToOldBaseDir)}${globWithoutPrefix}`;
@@ -284,7 +284,7 @@
}
// If it's only Windows drive letter, it needs \
- if (/^[A-Z]:$/.test(this._baseDir)) {
+ if (/^[A-Z]:$/u.test(this._baseDir)) {
this._baseDir += "\\";
}
@@ -300,7 +300,7 @@
*/
readIgnoreFile(filePath) {
if (typeof this.cache[filePath] === "undefined") {
- this.cache[filePath] = fs.readFileSync(filePath, "utf8").split(/\r?\n/g).filter(Boolean);
+ this.cache[filePath] = fs.readFileSync(filePath, "utf8").split(/\r?\n/gu).filter(Boolean);
}
return this.cache[filePath];
}

lib/util/interpolate.js

@@ -15,7 +15,7 @@
}
// Substitution content for any {{ }} markers.
- return text.replace(/\{\{([^{}]+?)\}\}/g, (fullMatch, termWithWhitespace) => {
+ return text.replace(/\{\{([^{}]+?)\}\}/gu, (fullMatch, termWithWhitespace) => {
const term = termWithWhitespace.trim();
if (term in data) {

lib/util/naming.js

@@ -13,7 +13,7 @@
// Private
//------------------------------------------------------------------------------
-const NAMESPACE_REGEX = /^@.*\//i;
+const NAMESPACE_REGEX = /^@.*\//iu;
/**
* Brings package name to correct format based on prefix
@@ -40,8 +40,8 @@
* it's a scoped package
* package name is the prefix, or just a username
*/
- const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`),
- scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`);
+ const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`, "u"),
+ scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`, "u");
if (scopedPackageShortcutRegex.test(normalizedName)) {
normalizedName = normalizedName.replace(scopedPackageShortcutRegex, `$1/${prefix}`);
@@ -51,7 +51,7 @@
* for scoped packages, insert the prefix after the first / unless
* the path is already @scope/eslint or @scope/eslint-xxx-yyy
*/
- normalizedName = normalizedName.replace(/^@([^/]+)\/(.*)$/, `@$1/${prefix}-$2`);
+ normalizedName = normalizedName.replace(/^@([^/]+)\/(.*)$/u, `@$1/${prefix}-$2`);
}
} else if (normalizedName.indexOf(`${prefix}-`) !== 0) {
normalizedName = `${prefix}-${normalizedName}`;
@@ -68,13 +68,13 @@
*/
function getShorthandName(fullname, prefix) {
if (fullname[0] === "@") {
- let matchResult = new RegExp(`^(@[^/]+)/${prefix}$`).exec(fullname);
+ let matchResult = new RegExp(`^(@[^/]+)/${prefix}$`, "u").exec(fullname);
if (matchResult) {
return matchResult[1];
}
- matchResult = new RegExp(`^(@[^/]+)/${prefix}-(.+)$`).exec(fullname);
+ matchResult = new RegExp(`^(@[^/]+)/${prefix}-(.+)$`, "u").exec(fullname);
if (matchResult) {
return `${matchResult[1]}/${matchResult[2]}`;
}

lib/util/node-event-generator.js

@@ -157,7 +157,7 @@
*/
function tryParseSelector(rawSelector) {
try {
- return esquery.parse(rawSelector.replace(/:exit$/, ""));
+ return esquery.parse(rawSelector.replace(/:exit$/u, ""));
} catch (err) {
if (typeof err.offset === "number") {
throw new SyntaxError(`Syntax error in selector "${rawSelector}" at position ${err.offset}: ${err.message}`);

lib/util/path-utils.js

@@ -22,7 +22,7 @@
*/
function convertPathToPosix(filepath) {
const normalizedFilepath = path.normalize(filepath);
- const posixFilepath = normalizedFilepath.replace(/\\/g, "/");
+ const posixFilepath = normalizedFilepath.replace(/\\/gu, "/");
return posixFilepath;
}
@@ -58,7 +58,7 @@
}
return path.relative(baseDir, absolutePath);
}
- return absolutePath.replace(/^\//, "");
+ return absolutePath.replace(/^\//u, "");
}

lib/util/patterns/letters.js

@@ -33,4 +33,4 @@
"use strict";
-module.exports = /[A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/;
+module.exports = /[A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/u;

lib/util/source-code.js

@@ -357,7 +357,7 @@
if (parent.type !== "CallExpression" && parent.type !== "NewExpression") {
while (
!this.getCommentsBefore(parent).length &&
- !/Function/.test(parent.type) &&
+ !/Function/u.test(parent.type) &&
parent.type !== "MethodDefinition" &&
parent.type !== "Property"
) {
@@ -422,7 +422,7 @@
isSpaceBetweenTokens(first, second) {
const text = this.text.slice(first.range[1], second.range[0]);
- return /\s/.test(text.replace(/\/\*.*?\*\//g, ""));
+ return /\s/u.test(text.replace(/\/\*.*?\*\//gu, ""));
}
/**

lib/util/xml-escape.js

@@ -15,7 +15,7 @@
* @private
*/
module.exports = function(s) {
- return (`${s}`).replace(/[<>&"'\x00-\x1F\x7F\u0080-\uFFFF]/g, c => { // eslint-disable-line no-control-regex
+ return (`${s}`).replace(/[<>&"'\x00-\x1F\x7F\u0080-\uFFFF]/gu, c => { // eslint-disable-line no-control-regex
switch (c) {
case "<":
return "&lt;";

package.json

@@ -1,6 +1,6 @@
{
"name": "eslint",
- "version": "5.12.0",
+ "version": "5.16.0",
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
"description": "An AST-based pattern checker for JavaScript.",
"bin": {
@@ -18,7 +18,7 @@
"publish-release": "node Makefile.js publishRelease",
"docs": "node Makefile.js docs",
"gensite": "node Makefile.js gensite",
- "browserify": "node Makefile.js browserify",
+ "webpack": "node Makefile.js webpack",
"perf": "node Makefile.js perf",
"profile": "beefy tests/bench/bench.js --open -- -t brfs -t ./tests/bench/xform-rules.js -r espree",
"coveralls": "cat ./coverage/lcov.info | coveralls"
@@ -36,82 +36,83 @@
"bugs": "https://github.com/eslint/eslint/issues/",
"dependencies": {
"@babel/code-frame": "^7.0.0",
- "ajv": "^6.5.3",
+ "ajv": "^6.9.1",
"chalk": "^2.1.0",
"cross-spawn": "^6.0.5",
"debug": "^4.0.1",
- "doctrine": "^2.1.0",
- "eslint-scope": "^4.0.0",
+ "doctrine": "^3.0.0",
+ "eslint-scope": "^4.0.3",
"eslint-utils": "^1.3.1",
"eslint-visitor-keys": "^1.0.0",
- "espree": "^5.0.0",
+ "espree": "^5.0.1",
"esquery": "^1.0.1",
"esutils": "^2.0.2",
- "file-entry-cache": "^2.0.0",
+ "file-entry-cache": "^5.0.1",
"functional-red-black-tree": "^1.0.1",
"glob": "^7.1.2",
"globals": "^11.7.0",
"ignore": "^4.0.6",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
- "inquirer": "^6.1.0",
- "js-yaml": "^3.12.0",
+ "inquirer": "^6.2.2",
+ "js-yaml": "^3.13.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.3.0",
- "lodash": "^4.17.5",
+ "lodash": "^4.17.11",
"minimatch": "^3.0.4",
"mkdirp": "^0.5.1",
"natural-compare": "^1.4.0",
"optionator": "^0.8.2",
"path-is-inside": "^1.0.2",
- "pluralize": "^7.0.0",
"progress": "^2.0.0",
"regexpp": "^2.0.1",
"semver": "^5.5.1",
"strip-ansi": "^4.0.0",
"strip-json-comments": "^2.0.1",
- "table": "^5.0.2",
+ "table": "^5.2.3",
"text-table": "^0.2.0"
},
"devDependencies": {
- "babel-core": "^6.26.3",
- "babel-polyfill": "^6.26.0",
- "babel-preset-es2015": "^6.24.1",
- "babelify": "^8.0.0",
+ "@babel/core": "^7.2.2",
+ "@babel/polyfill": "^7.2.5",
+ "@babel/preset-env": "^7.3.1",
+ "babel-loader": "^8.0.5",
"beefy": "^2.1.8",
"brfs": "^2.0.0",
- "browserify": "^16.2.2",
"chai": "^4.0.1",
"cheerio": "^0.22.0",
+ "common-tags": "^1.8.0",
"coveralls": "^3.0.1",
"dateformat": "^3.0.3",
"ejs": "^2.6.1",
+ "eslint-config-eslint": "file:packages/eslint-config-eslint",
"eslint-plugin-eslint-plugin": "^2.0.1",
+ "eslint-plugin-internal-rules": "file:tools/internal-rules",
"eslint-plugin-node": "^8.0.0",
- "eslint-plugin-rulesdir": "^0.1.0",
"eslint-release": "^1.2.0",
- "eslint-rule-composer": "^0.3.0",
- "eslump": "^1.6.2",
+ "eslump": "^2.0.0",
"esprima": "^4.0.1",
- "istanbul": "^0.4.5",
"jsdoc": "^3.5.5",
- "karma": "^3.0.0",
- "karma-babel-preprocessor": "^7.0.0",
+ "karma": "^3.1.4",
"karma-chrome-launcher": "^2.2.0",
"karma-mocha": "^1.3.0",
"karma-mocha-reporter": "^2.2.3",
+ "karma-webpack": "^4.0.0-rc.6",
"leche": "^2.2.3",
"load-perf": "^0.2.0",
- "markdownlint": "^0.11.0",
+ "markdownlint": "^0.12.0",
"mocha": "^5.0.5",
- "mock-fs": "^4.6.0",
+ "mock-fs": "^4.8.0",
"npm-license": "^0.3.3",
+ "nyc": "^13.3.0",
"proxyquire": "^2.0.1",
- "puppeteer": "^1.9.0",
+ "puppeteer": "^1.12.2",
"shelljs": "^0.8.2",
"sinon": "^3.3.0",
- "temp": "^0.8.3",
- "through": "^2.3.8"
+ "temp": "^0.9.0",
+ "through": "^2.3.8",
+ "webpack": "^4.29.3",
+ "webpack-cli": "^3.2.3"
},
"keywords": [
"ast",

README.md

@@ -133,7 +133,7 @@
* Make sure your plugins (and ESLint) are both in your project's `package.json` as devDependencies (or dependencies, if your project uses ESLint at runtime).
* Make sure you have run `npm install` and all your dependencies are installed.
-In all cases, make sure your plugins' peerDependencies have been installed as well. You can use `npm view eslint-plugin-myplugin peerDepencies` to see what peer dependencies `eslint-plugin-myplugin` has.
+In all cases, make sure your plugins' peerDependencies have been installed as well. You can use `npm view eslint-plugin-myplugin peerDependencies` to see what peer dependencies `eslint-plugin-myplugin` has.
### Does ESLint support JSX?
@@ -193,153 +193,91 @@
These folks keep the project moving and are resources for help.
+<!-- NOTE: This section is autogenerated. Do not manually edit.-->
+<!--teamstart-->
+
### Technical Steering Committee (TSC)
-<table>
- <tbody>
- <tr>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/nzakas">
- <img src="https://github.com/nzakas.png?s=75" width="75px" height="75px"><br/>
- <sub>Nicholas C. Zakas</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/ilyavolodin">
- <img src="https://github.com/ilyavolodin.png?s=75" width="75px" height="75px"><br/>
- <sub>Ilya Volodin</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/btmills">
- <img src="https://github.com/btmills.png?s=75" width="75px" height="75px"><br/>
- <sub>Brandon Mills</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/gyandeeps">
- <img src="https://github.com/gyandeeps.png?s=75" width="75px" height="75px"><br/>
- <sub>Gyandeep Singh</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/mysticatea">
- <img src="https://github.com/mysticatea.png?s=75" width="75px" height="75px"><br/>
- <sub>Toru Nagashima</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/alberto">
- <img src="https://github.com/alberto.png?s=75" width="75px" height="75px"><br/>
- <sub>Alberto Rodríguez</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/kaicataldo">
- <img src="https://github.com/kaicataldo.png?s=75" width="75px" height="75px"><br/>
- <sub>Kai Cataldo</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/not-an-aardvark">
- <img src="https://github.com/not-an-aardvark.png?s=75" width="75px" height="75px"><br/>
- <sub>Teddy Katz</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/platinumazure">
- <img src="https://github.com/platinumazure.png?s=75" width="75px" height="75px"><br/>
- <sub>Kevin Partington</sub></a>
- </td>
- </tr>
- </tbody>
-</table>
-
-### Development Team
-
-<table>
- <tbody>
- <tr>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/lo1tuma">
- <img src="https://github.com/lo1tuma.png?s=75" width="75px" height="75px"><br/>
- <sub>Mathias Schreck</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/xjamundx">
- <img src="https://github.com/xjamundx.png?s=75" width="75px" height="75px"><br/>
- <sub>Jamund Ferguson</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/ianvs">
- <img src="https://github.com/ianvs.png?s=75" width="75px" height="75px"><br/>
- <sub>Ian VanSchooten</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/byk">
- <img src="https://github.com/byk.png?s=75" width="75px" height="75px"><br/>
- <sub>Burak Yiğit Kaya</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/michaelficarra">
- <img src="https://github.com/michaelficarra.png?s=75" width="75px" height="75px"><br/>
- <sub>Michael Ficarra</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/pedrottimark">
- <img src="https://github.com/pedrottimark.png?s=75" width="75px" height="75px"><br/>
- <sub>Mark Pedrotti</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/markelog">
- <img src="https://github.com/markelog.png?s=75" width="75px" height="75px"><br/>
- <sub>Oleg Gaidarenko</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/mikesherov">
- <img src="https://github.com/mikesherov.png?s=75" width="75px" height="75px"><br/>
- <sub>Mike Sherov</sub></a>
- </td>
- </tr>
- <tr>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/hzoo">
- <img src="https://github.com/hzoo.png?s=75" width="75px" height="75px"><br/>
- <sub>Henry Zhu</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/mdevils">
- <img src="https://github.com/mdevils.png?s=75" width="75px" height="75px"><br/>
- <sub>Marat Dulin</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/zxqfox">
- <img src="https://github.com/zxqfox.png?s=75" width="75px" height="75px"><br/>
- <sub>Alexej Yaroshevich</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/vitorbal">
- <img src="https://github.com/vitorbal.png?s=75" width="75px" height="75px"><br/>
- <sub>Vitor Balocco</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/JamesHenry">
- <img src="https://github.com/JamesHenry.png?s=75" width="75px" height="75px"><br/>
- <sub>James Henry</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/soda0289">
- <img src="https://github.com/soda0289.png?s=75" width="75px" height="75px"><br/>
- <sub>Reyad Attiyat</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/Aladdin-ADD">
- <img src="https://github.com/Aladdin-ADD.png?s=75" width="75px" height="75px"><br/>
- <sub>薛定谔��猫</sub></a>
- </td>
- <td align="center" valign="top" width="11%">
- <a href="https://github.com/VictorHom">
- <img src="https://github.com/VictorHom.png?s=75" width="75px" height="75px"><br/>
- <sub>Victor Hom</sub></a>
- </td>
- </tr>
- </tbody>
-</table>
+The people who manage releases, review feature requests, and meet regularly to ensure ESLint is properly maintained.
+
+<table><tbody><tr><td align="center" valign="top" width="11%">
+<a href="https://github.com/nzakas">
+<img src="https://github.com/nzakas.png?s=75" width="75" height="75"><br />
+Nicholas C. Zakas
+</a>
+</td><td align="center" valign="top" width="11%">
+<a href="https://github.com/platinumazure">
+<img src="https://github.com/platinumazure.png?s=75" width="75" height="75"><br />
+Kevin Partington
+</a>
+</td><td align="center" valign="top" width="11%">
+<a href="https://github.com/ilyavolodin">
+<img src="https://github.com/ilyavolodin.png?s=75" width="75" height="75"><br />
+Ilya Volodin
+</a>
+</td><td align="center" valign="top" width="11%">
+<a href="https://github.com/btmills">
+<img src="https://github.com/btmills.png?s=75" width="75" height="75"><br />
+Brandon Mills
+</a>
+</td><td align="center" valign="top" width="11%">
+<a href="https://github.com/mysticatea">
+<img src="https://github.com/mysticatea.png?s=75" width="75" height="75"><br />
+Toru Nagashima
+</a>
+</td><td align="center" valign="top" width="11%">
+<a href="https://github.com/gyandeeps">
+<img src="https://github.com/gyandeeps.png?s=75" width="75" height="75"><br />
+Gyandeep Singh
+</a>
+</td><td align="center" valign="top" width="11%">
+<a href="https://github.com/kaicataldo">
+<img src="https://github.com/kaicataldo.png?s=75" width="75" height="75"><br />
+Kai Cataldo
+</a>
+</td><td align="center" valign="top" width="11%">
+<a href="https://github.com/not-an-aardvark">
+<img src="https://github.com/not-an-aardvark.png?s=75" width="75" height="75"><br />
+Teddy Katz
+</a>
+</td></tr></tbody></table>
+
+
+
+
+### Committers
+
+The people who review and fix bugs and help triage issues.
+
+<table><tbody><tr><td align="center" valign="top" width="11%">
+<a href="https://github.com/aladdin-add">
+<img src="https://github.com/aladdin-add.png?s=75" width="75" height="75"><br />
+薛定谔的猫
+</a>
+</td><td align="center" valign="top" width="11%">
+<a href="https://github.com/g-plane">
+<img src="https://github.com/g-plane.png?s=75" width="75" height="75"><br />
+Pig Fang
+</a>
+</td></tr></tbody></table>
+
+
+<!--teamend-->
## Sponsors
+The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://opencollective.com/eslint) to get your logo on our README and website.
+
+<!-- NOTE: This section is autogenerated. Do not manually edit.-->
+<!--sponsorsstart-->
+<h3>Gold Sponsors</h3>
+<p><a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Fopencollective-production.s3-us-west-1.amazonaws.com%2F098e3bd0-4d57-11e8-9324-0f6cc1f92bf1.png&height=96" alt="Airbnb" height="96"></a> <a href="https://code.facebook.com/projects/"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Fres.cloudinary.com%2Fopencollective%2Fimage%2Fupload%2Fv1508519428%2FS9gk78AS_400x400_fulq2l.jpg&height=96" alt="Facebook Open Source" height="96"></a> <a href="https://badoo.com/team?utm_source=eslint"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Fopencollective-production.s3-us-west-1.amazonaws.com%2Fbbdb9cc0-3b5d-11e9-9537-ad85092287b8.png&height=96" alt="Badoo" height="96"></a></p><h3>Silver Sponsors</h3>
+<p><a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Fopencollective-production.s3-us-west-1.amazonaws.com%2F68ed8b70-ebf2-11e6-9958-cb7e79408c56.png&height=96" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
+<p><a href="http://faithlife.com/ref/about"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Flogo.clearbit.com%2Ffaithlife.com&height=96" alt="Faithlife" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Flogo.clearbit.com%2Fjsheroes.io&height=96" alt="JSHeroes " height="32"></a></p>
+<!--sponsorsend-->
+
+## Technology Sponsors
+
* Site search ([eslint.org](https://eslint.org)) is sponsored by [Algolia](https://www.algolia.com)