linter: missing-constructor-super
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 c60aed2..ba4de97 100644
--- a/linter/src/main/java/org/apache/royale/linter/LINTER.java
+++ b/linter/src/main/java/org/apache/royale/linter/LINTER.java
@@ -71,6 +71,7 @@
import org.apache.royale.linter.rules.MaxBlockDepthRule;
import org.apache.royale.linter.rules.MaxParametersRule;
import org.apache.royale.linter.rules.MissingASDocRule;
+import org.apache.royale.linter.rules.MissingConstructorSuperRule;
import org.apache.royale.linter.rules.MissingNamespaceRule;
import org.apache.royale.linter.rules.MissingSemicolonRule;
import org.apache.royale.linter.rules.MissingTypeRule;
@@ -321,6 +322,9 @@
if (configuration.getMissingAsdoc()) {
rules.add(new MissingASDocRule());
}
+ if (configuration.getMissingConstructorSuper()) {
+ rules.add(new MissingConstructorSuperRule());
+ }
if (configuration.getMissingNamespace()) {
rules.add(new MissingNamespaceRule());
}
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 07b3378..5d19751 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
@@ -555,6 +555,22 @@
}
//
+ // 'missing-constructor-super' option
+ //
+
+ private boolean missingConstructorSuper = false;
+
+ public boolean getMissingConstructorSuper() {
+ return missingConstructorSuper;
+ }
+
+ @Config
+ @Mapping("missing-constructor-super")
+ public void setMissingConstructorSuper(ConfigurationValue cv, boolean b) {
+ this.missingConstructorSuper = b;
+ }
+
+ //
// 'missing-namespace' option
//
diff --git a/linter/src/main/java/org/apache/royale/linter/rules/MissingConstructorSuperRule.java b/linter/src/main/java/org/apache/royale/linter/rules/MissingConstructorSuperRule.java
new file mode 100644
index 0000000..f2863b7
--- /dev/null
+++ b/linter/src/main/java/org/apache/royale/linter/rules/MissingConstructorSuperRule.java
@@ -0,0 +1,93 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.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.IExpressionNode;
+import org.apache.royale.compiler.tree.as.IFunctionCallNode;
+import org.apache.royale.compiler.tree.as.IFunctionNode;
+import org.apache.royale.compiler.tree.as.ILanguageIdentifierNode;
+import org.apache.royale.compiler.tree.as.ILanguageIdentifierNode.LanguageIdentifierKind;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.NodeVisitor;
+import org.apache.royale.linter.TokenQuery;
+
+/**
+ * Check that all constructors include a call to super().
+ */
+public class MissingConstructorSuperRule extends LinterRule {
+ @Override
+ public Map<ASTNodeID, NodeVisitor> getNodeVisitors() {
+ Map<ASTNodeID, NodeVisitor> result = new HashMap<>();
+ result.put(ASTNodeID.FunctionID, (node, tokenQuery, problems) -> {
+ checkFunctionNode((IFunctionNode) node, tokenQuery, problems);
+ });
+ return result;
+ }
+
+ private void checkFunctionNode(IFunctionNode functionNode, TokenQuery tokenQuery, Collection<ICompilerProblem> problems) {
+ if (!functionNode.isConstructor()) {
+ return;
+ }
+ if (hasSuperCall(functionNode.getScopedNode())) {
+ return;
+ }
+ problems.add(new MissingConstructorSuperLinterProblem(functionNode));
+ }
+
+ private boolean hasSuperCall(IASNode node) {
+ if (node instanceof IFunctionCallNode) {
+ IFunctionCallNode functionCallNode = (IFunctionCallNode) node;
+ IExpressionNode nameNode = functionCallNode.getNameNode();
+ if (nameNode instanceof ILanguageIdentifierNode) {
+ ILanguageIdentifierNode identifierNode = (ILanguageIdentifierNode) nameNode;
+ if (LanguageIdentifierKind.SUPER.equals(identifierNode.getKind())) {
+ return true;
+ }
+ }
+ }
+ for (int i = 0; i < node.getChildCount(); i++) {
+ IASNode child = node.getChild(i);
+ if (hasSuperCall(child)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static class MissingConstructorSuperLinterProblem extends CompilerProblem {
+ public static final String DESCRIPTION = "Constructor '${functionName}' does not include 'super()' call";
+
+ public MissingConstructorSuperLinterProblem(IFunctionNode node)
+ {
+ super(node.getNameExpressionNode());
+ functionName = node.getName();
+ }
+
+ public String functionName;
+ }
+}