linter: sparse-array
diff --git a/linter/src/main/java/org/apache/royale/linter/LINTER.java b/linter/src/main/java/org/apache/royale/linter/LINTER.java
index 03d6c05..e8ca277 100644
--- a/linter/src/main/java/org/apache/royale/linter/LINTER.java
+++ b/linter/src/main/java/org/apache/royale/linter/LINTER.java
@@ -79,6 +79,7 @@
 import org.apache.royale.linter.rules.NumericLeadingZeroesRule;
 import org.apache.royale.linter.rules.OverrideContainsOnlySuperCallRule;
 import org.apache.royale.linter.rules.PackageNameRule;
+import org.apache.royale.linter.rules.SparseArrayRule;
 import org.apache.royale.linter.rules.StaticConstantsRule;
 import org.apache.royale.linter.rules.StrictEqualityRule;
 import org.apache.royale.linter.rules.StringEventNameRule;
@@ -347,6 +348,9 @@
 			if (configuration.getPackageName()) {
 				rules.add(new PackageNameRule());
 			}
+			if (configuration.getSparseArray()) {
+				rules.add(new SparseArrayRule());
+			}
 			if (configuration.getStaticConstants()) {
 				rules.add(new StaticConstantsRule());
 			}
diff --git a/linter/src/main/java/org/apache/royale/linter/config/Configuration.java b/linter/src/main/java/org/apache/royale/linter/config/Configuration.java
index 7aac037..0e02a0e 100644
--- a/linter/src/main/java/org/apache/royale/linter/config/Configuration.java
+++ b/linter/src/main/java/org/apache/royale/linter/config/Configuration.java
@@ -715,6 +715,22 @@
     }
 
     //
+    // 'sparse-array' option
+    //
+
+    private boolean sparseArray = false;
+
+    public boolean getSparseArray() {
+        return sparseArray;
+    }
+
+    @Config
+    @Mapping("sparse-array")
+    public void setSparseArray(ConfigurationValue cv, boolean b) {
+        this.sparseArray = b;
+    }
+
+    //
     // 'static-constants' option
     //
 
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/SparseArrayRule.java b/linter/src/main/java/org/apache/royale/linter/rules/SparseArrayRule.java
new file mode 100644
index 0000000..a6a7236
--- /dev/null
+++ b/linter/src/main/java/org/apache/royale/linter/rules/SparseArrayRule.java
@@ -0,0 +1,75 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package org.apache.royale.linter.rules;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.royale.compiler.internal.tree.as.ContainerNode;
+import org.apache.royale.compiler.problems.CompilerProblem;
+import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.compiler.tree.ASTNodeID;
+import org.apache.royale.compiler.tree.as.IASNode;
+import org.apache.royale.compiler.tree.as.ILiteralContainerNode;
+import org.apache.royale.compiler.tree.as.ILiteralNode.LiteralType;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.NodeVisitor;
+import org.apache.royale.linter.TokenQuery;
+
+/**
+ * Check that an array literal contains no empty slots (multiple repeating commas with no values).
+ */
+public class SparseArrayRule extends LinterRule {
+	@Override
+	public Map<ASTNodeID, NodeVisitor> getNodeVisitors() {
+		Map<ASTNodeID, NodeVisitor> result = new HashMap<>();
+		result.put(ASTNodeID.ArrayLiteralID, (node, tokenQuery, problems) -> {
+			checkLiteralContainerNode((ILiteralContainerNode) node, tokenQuery, problems);
+		});
+		return result;
+	}
+
+	private void checkLiteralContainerNode(ILiteralContainerNode arrayLiteralNode, TokenQuery tokenQuery, Collection<ICompilerProblem> problems) {
+		if (!LiteralType.ARRAY.equals(arrayLiteralNode.getLiteralType())) {
+			return;
+		}
+		ContainerNode contentsNode = arrayLiteralNode.getContentsNode();
+		if (contentsNode == null) {
+			return;
+		}
+		for (int i = 0; i < contentsNode.getChildCount(); i++) {
+			IASNode child = contentsNode.getChild(i);
+			if (ASTNodeID.NilID.equals(child.getNodeID())) {
+				problems.add(new SparseArrayLinterProblem(arrayLiteralNode));
+				return;
+			}
+		}
+	}
+
+	public static class SparseArrayLinterProblem extends CompilerProblem {
+		public static final String DESCRIPTION = "Array literals must not be sparse";
+
+		public SparseArrayLinterProblem(ILiteralContainerNode node)
+		{
+			super(node);
+		}
+	}
+}