diff --git a/README.md b/README.md
index 7e9cb446..8ca2bd38 100644
--- a/README.md
+++ b/README.md
@@ -154,6 +154,7 @@ The rules with the following star :star: are included in the config.
| [jsonc/no-dupe-keys](https://ota-meshi.github.io/eslint-plugin-jsonc/rules/no-dupe-keys.html) | disallow duplicate keys in object literals | | :star: | :star: | :star: |
| [jsonc/no-multi-str](https://ota-meshi.github.io/eslint-plugin-jsonc/rules/no-multi-str.html) | disallow multiline strings | | :star: | :star: | |
| [jsonc/no-octal-escape](https://ota-meshi.github.io/eslint-plugin-jsonc/rules/no-octal-escape.html) | disallow octal escape sequences in string literals | | | | |
+| [jsonc/no-sparse-arrays](https://ota-meshi.github.io/eslint-plugin-jsonc/rules/no-sparse-arrays.html) | disallow sparse arrays | | :star: | :star: | :star: |
| [jsonc/no-useless-escape](https://ota-meshi.github.io/eslint-plugin-jsonc/rules/no-useless-escape.html) | disallow unnecessary escape usage | | :star: | :star: | :star: |
| [jsonc/object-curly-newline](https://ota-meshi.github.io/eslint-plugin-jsonc/rules/object-curly-newline.html) | enforce consistent line breaks inside braces | :wrench: | | | |
| [jsonc/object-curly-spacing](https://ota-meshi.github.io/eslint-plugin-jsonc/rules/object-curly-spacing.html) | enforce consistent spacing inside braces | :wrench: | | | |
diff --git a/docs/rules/README.md b/docs/rules/README.md
index a84a2a23..645a7ade 100644
--- a/docs/rules/README.md
+++ b/docs/rules/README.md
@@ -32,6 +32,7 @@ The rules with the following star :star: are included in the `plugin:jsonc/recom
| [jsonc/no-dupe-keys](./no-dupe-keys.md) | disallow duplicate keys in object literals | | :star: | :star: | :star: |
| [jsonc/no-multi-str](./no-multi-str.md) | disallow multiline strings | | :star: | :star: | |
| [jsonc/no-octal-escape](./no-octal-escape.md) | disallow octal escape sequences in string literals | | | | |
+| [jsonc/no-sparse-arrays](./no-sparse-arrays.md) | disallow sparse arrays | | :star: | :star: | :star: |
| [jsonc/no-useless-escape](./no-useless-escape.md) | disallow unnecessary escape usage | | :star: | :star: | :star: |
| [jsonc/object-curly-newline](./object-curly-newline.md) | enforce consistent line breaks inside braces | :wrench: | | | |
| [jsonc/object-curly-spacing](./object-curly-spacing.md) | enforce consistent spacing inside braces | :wrench: | | | |
diff --git a/docs/rules/no-sparse-arrays.md b/docs/rules/no-sparse-arrays.md
new file mode 100644
index 00000000..1b45b5b5
--- /dev/null
+++ b/docs/rules/no-sparse-arrays.md
@@ -0,0 +1,51 @@
+---
+pageClass: "rule-details"
+sidebarDepth: 0
+title: "jsonc/no-sparse-arrays"
+description: "disallow sparse arrays"
+---
+# jsonc/no-sparse-arrays
+
+> disallow sparse arrays
+
+- :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
+
+## :book: Rule Details
+
+This rule disallows sparse array literals which have "holes" where commas are not preceded by elements. It does not apply to a trailing comma following the last element.
+
+JSON, JSONC and JSON5 do not allow arrays contain empty slots.
+
+
+
+```json5
+/* eslint jsonc/no-sparse-arrays: 'error' */
+{
+ /* ✓ GOOD */
+ "GOOD": [1, 2, 3, 4],
+ "GOOD": [1, 2, 3, 4,],
+
+ /* ✗ BAD */
+ "BAD": [1, , , 4],
+ "BAD": [, 2, 3, 4]
+}
+```
+
+
+
+## :wrench: Options
+
+Nothing.
+
+## :couple: Related rules
+
+- [no-sparse-arrays]
+
+[no-sparse-arrays]: https://eslint.org/docs/rules/no-sparse-arrays
+
+## Implementation
+
+- [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-sparse-arrays.ts)
+- [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-sparse-arrays.js)
+
+Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/no-sparse-arrays)
diff --git a/lib/configs/recommended-with-json.ts b/lib/configs/recommended-with-json.ts
index dda6ff42..0e7653e2 100644
--- a/lib/configs/recommended-with-json.ts
+++ b/lib/configs/recommended-with-json.ts
@@ -10,6 +10,7 @@ export = {
"jsonc/no-comments": "error",
"jsonc/no-dupe-keys": "error",
"jsonc/no-multi-str": "error",
+ "jsonc/no-sparse-arrays": "error",
"jsonc/no-template-literals": "error",
"jsonc/no-undefined-value": "error",
"jsonc/no-useless-escape": "error",
diff --git a/lib/configs/recommended-with-json5.ts b/lib/configs/recommended-with-json5.ts
index 4dee377d..85619488 100644
--- a/lib/configs/recommended-with-json5.ts
+++ b/lib/configs/recommended-with-json5.ts
@@ -7,6 +7,7 @@ export = {
rules: {
// eslint-plugin-jsonc rules
"jsonc/no-dupe-keys": "error",
+ "jsonc/no-sparse-arrays": "error",
"jsonc/no-template-literals": "error",
"jsonc/no-undefined-value": "error",
"jsonc/no-useless-escape": "error",
diff --git a/lib/configs/recommended-with-jsonc.ts b/lib/configs/recommended-with-jsonc.ts
index fe69b15e..3f0db8dd 100644
--- a/lib/configs/recommended-with-jsonc.ts
+++ b/lib/configs/recommended-with-jsonc.ts
@@ -8,6 +8,7 @@ export = {
// eslint-plugin-jsonc rules
"jsonc/no-dupe-keys": "error",
"jsonc/no-multi-str": "error",
+ "jsonc/no-sparse-arrays": "error",
"jsonc/no-template-literals": "error",
"jsonc/no-undefined-value": "error",
"jsonc/no-useless-escape": "error",
diff --git a/lib/rules/no-sparse-arrays.ts b/lib/rules/no-sparse-arrays.ts
new file mode 100644
index 00000000..c21d7e13
--- /dev/null
+++ b/lib/rules/no-sparse-arrays.ts
@@ -0,0 +1,19 @@
+import coreRule from "eslint/lib/rules/no-sparse-arrays"
+import { createRule, defineWrapperListener } from "../utils"
+
+export default createRule("no-sparse-arrays", {
+ meta: {
+ docs: {
+ description: "disallow sparse arrays",
+ recommended: ["json", "jsonc", "json5"],
+ extensionRule: true,
+ },
+ fixable: coreRule.meta!.fixable,
+ schema: coreRule.meta!.schema!,
+ messages: coreRule.meta!.messages!,
+ type: coreRule.meta!.type!,
+ },
+ create(context) {
+ return defineWrapperListener(coreRule, context, context.options)
+ },
+})
diff --git a/lib/utils/rules.ts b/lib/utils/rules.ts
index 2f9892c8..4ae8b3a9 100644
--- a/lib/utils/rules.ts
+++ b/lib/utils/rules.ts
@@ -10,6 +10,7 @@ import noComments from "../rules/no-comments"
import noDupeKeys from "../rules/no-dupe-keys"
import noMultiStr from "../rules/no-multi-str"
import noOctalEscape from "../rules/no-octal-escape"
+import noSparseArrays from "../rules/no-sparse-arrays"
import noTemplateLiterals from "../rules/no-template-literals"
import noUndefinedValue from "../rules/no-undefined-value"
import noUselessEscape from "../rules/no-useless-escape"
@@ -33,6 +34,7 @@ export const rules = [
noDupeKeys,
noMultiStr,
noOctalEscape,
+ noSparseArrays,
noTemplateLiterals,
noUndefinedValue,
noUselessEscape,
diff --git a/tests/lib/rules/no-sparse-arrays.ts b/tests/lib/rules/no-sparse-arrays.ts
new file mode 100644
index 00000000..c6c94074
--- /dev/null
+++ b/tests/lib/rules/no-sparse-arrays.ts
@@ -0,0 +1,20 @@
+import { RuleTester } from "eslint"
+import rule from "../../../lib/rules/no-sparse-arrays"
+
+const tester = new RuleTester({
+ parser: require.resolve("../../../lib/parser/json-eslint-parser"),
+})
+
+tester.run("no-sparse-arrays", rule as any, {
+ valid: ["[1,2,3,4]", "[1,2,3,4,]"],
+ invalid: [
+ {
+ code: "[1,,,4]",
+ errors: ["Unexpected comma in middle of array."],
+ },
+ {
+ code: "[,2,3,4]",
+ errors: ["Unexpected comma in middle of array."],
+ },
+ ],
+})
diff --git a/tools/new-rule.ts b/tools/new-rule.ts
index 1c3bd8d8..a9109e7d 100644
--- a/tools/new-rule.ts
+++ b/tools/new-rule.ts
@@ -32,10 +32,10 @@ export default createRule("${ruleId}", {
description: "...",
recommended: true,
},
- fixable: coreRule.meta?.fixable,
- schema: coreRule.meta?.schema!,
- messages: coreRule.meta?.messages!,
- type: coreRule.meta?.type!,
+ fixable: coreRule.meta!.fixable,
+ schema: coreRule.meta!.schema!,
+ messages: coreRule.meta!.messages!,
+ type: coreRule.meta!.type!,
},
create(context) {
return defineWrapperListener(coreRule, context, context.options)