This is an automated email from the ASF dual-hosted git repository.

joshtynjala pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git

commit 6d569104b1c94fef1b86d6ce285ae0fda533f729
Author: Josh Tynjala <[email protected]>
AuthorDate: Mon Sep 26 14:48:36 2022 -0700

    linter: vars-on-top
---
 .../main/java/org/apache/royale/linter/LINTER.java |  4 +
 .../apache/royale/linter/config/Configuration.java | 16 ++++
 .../royale/linter/rules/VariablesOnTopRule.java    | 89 ++++++++++++++++++++++
 3 files changed, 109 insertions(+)

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 09d6442a0..1cb85902d 100644
--- a/linter/src/main/java/org/apache/royale/linter/LINTER.java
+++ b/linter/src/main/java/org/apache/royale/linter/LINTER.java
@@ -88,6 +88,7 @@ import org.apache.royale.linter.rules.ThisInClosureRule;
 import org.apache.royale.linter.rules.TraceRule;
 import org.apache.royale.linter.rules.UnsafeNegationRule;
 import org.apache.royale.linter.rules.ValidTypeofRule;
+import org.apache.royale.linter.rules.VariablesOnTopRule;
 import org.apache.royale.linter.rules.WildcardImportRule;
 import org.apache.royale.linter.rules.WithRule;
 import org.apache.royale.utils.FilenameNormalization;
@@ -374,6 +375,9 @@ public class LINTER {
                        if (configuration.getValidTypeof()) {
                                rules.add(new ValidTypeofRule());
                        }
+                       if (configuration.getVarsOnTop()) {
+                               rules.add(new VariablesOnTopRule());
+                       }
                        if (configuration.getWildcardImport()) {
                                rules.add(new WildcardImportRule());
                        }
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 1faa79e85..9459b370a 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
@@ -858,6 +858,22 @@ public class Configuration {
         this.validTypeof = b;
     }
 
+    //
+    // 'vars-on-top' option
+    //
+
+    private boolean varsOnTop = false;
+
+    public boolean getVarsOnTop() {
+        return varsOnTop;
+    }
+
+    @Config
+    @Mapping("vars-on-top")
+    public void setVarsOnTop(ConfigurationValue cv, boolean b) {
+        this.varsOnTop = b;
+    }
+
     //
     // 'wildcard-import' option
     //
diff --git 
a/linter/src/main/java/org/apache/royale/linter/rules/VariablesOnTopRule.java 
b/linter/src/main/java/org/apache/royale/linter/rules/VariablesOnTopRule.java
new file mode 100644
index 000000000..a6ae31f94
--- /dev/null
+++ 
b/linter/src/main/java/org/apache/royale/linter/rules/VariablesOnTopRule.java
@@ -0,0 +1,89 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.IFunctionNode;
+import org.apache.royale.compiler.tree.as.IScopedNode;
+import org.apache.royale.compiler.tree.as.IVariableNode;
+import org.apache.royale.linter.LinterRule;
+import org.apache.royale.linter.NodeVisitor;
+import org.apache.royale.linter.TokenQuery;
+
+/**
+ * Check that variables are always declared at the top of a function.
+ */
+public class VariablesOnTopRule 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) {
+               IScopedNode scopedNode = functionNode.getScopedNode();
+               if (scopedNode == null) {
+                       return;
+               }
+               boolean afterNonVariable = false;
+               for (int i = 0; i < scopedNode.getChildCount(); i++) {
+                       IASNode child = scopedNode.getChild(i);
+                       afterNonVariable = checkVariablesNotAtTop(child, 
afterNonVariable, problems);
+               }
+       }
+
+       private boolean checkVariablesNotAtTop(IASNode node, boolean 
afterNonVariable, Collection<ICompilerProblem> problems) {
+               if (node instanceof IVariableNode) {
+                       IVariableNode variableNode = (IVariableNode) node;
+                       if (afterNonVariable) {
+                               problems.add(new 
VariablesOnTopLinterProblem(variableNode));
+                       }
+                       return afterNonVariable;
+               }
+               afterNonVariable = true;
+               for (int i = 0; i < node.getChildCount(); i++) {
+                       IASNode child = node.getChild(i);
+                       afterNonVariable = checkVariablesNotAtTop(child, 
afterNonVariable, problems);
+               }
+               return afterNonVariable;
+       }
+
+       public static class VariablesOnTopLinterProblem extends CompilerProblem 
{
+               public static final String DESCRIPTION = "Variable name 
'${varName}' must be declared at the top of this function";
+
+               public VariablesOnTopLinterProblem(IVariableNode node)
+               {
+                       super(node.getNameExpressionNode());
+                       varName = node.getName();
+               }
+
+               public String varName;
+       }
+}

Reply via email to