You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by pi...@apache.org on 2019/09/16 08:07:09 UTC

[royale-compiler] 02/06: compiler: warn when using this in a function closure (references #90)

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

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

commit 5c9bf227eaf866cb0da66f0b1b54dd951ec95a00
Author: Josh Tynjala <jo...@apache.org>
AuthorDate: Wed Sep 11 13:18:52 2019 -0700

    compiler: warn when using this in a function closure (references #90)
    
    (cherry picked from commit 7e7b269bc922080e9084f757e3eecfa5c94697b9)
---
 .../semantics/MethodBodySemanticChecker.java       | 26 ++++++++++++++
 .../compiler/internal/semantics/SemanticUtils.java | 16 +++++++++
 .../problems/ThisUsedInClosureProblem.java         | 40 ++++++++++++++++++++++
 3 files changed, 82 insertions(+)

diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/MethodBodySemanticChecker.java b/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/MethodBodySemanticChecker.java
index 610da6d..c455528 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/MethodBodySemanticChecker.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/MethodBodySemanticChecker.java
@@ -789,6 +789,14 @@ public class MethodBodySemanticChecker
         {
             FunctionNode func = (FunctionNode)iNode;
 
+            if (SemanticUtils.isFunctionClosure(func))
+            {
+                for (IASNode thisNode : findThisIdentifierNodes(func))
+                {
+                    addProblem(new ThisUsedInClosureProblem(thisNode));
+                }
+            }
+
             IDefinition def = func.getDefinition();
 
             if ( project.getAllowAbstractClasses()
@@ -810,6 +818,24 @@ public class MethodBodySemanticChecker
         }
     }
 
+    private static List<IASNode> findThisIdentifierNodes(IASNode iNode)
+    {
+        List<IASNode> result = new ArrayList<IASNode>();
+        for(int i = 0, count = iNode.getChildCount(); i < count; i++)
+        {
+            IASNode child = iNode.getChild(i);
+            if(SemanticUtils.isThisKeyword(child))
+            {
+                result.add(child);
+            }
+            else if(!child.isTerminal() && !(child instanceof IFunctionNode))
+            {
+                result.addAll(findThisIdentifierNodes(child));
+            }
+        }
+        return result;
+    }
+
     public void checkNativeMethod(IASNode iNode)
     {
         if( iNode instanceof FunctionNode )
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/SemanticUtils.java b/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/SemanticUtils.java
index 20b3747..d22d291 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/SemanticUtils.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/SemanticUtils.java
@@ -129,6 +129,7 @@ import org.apache.royale.compiler.tree.as.IMemberAccessExpressionNode;
 import org.apache.royale.compiler.tree.as.INamespaceDecorationNode;
 import org.apache.royale.compiler.tree.as.INumericLiteralNode;
 import org.apache.royale.compiler.tree.as.IParameterNode;
+import org.apache.royale.compiler.tree.as.IScopedNode;
 import org.apache.royale.compiler.tree.as.ITryNode;
 import org.apache.royale.compiler.tree.as.IVariableNode;
 import org.apache.royale.compiler.tree.mxml.IMXMLEventSpecifierNode;
@@ -1324,6 +1325,21 @@ public class SemanticUtils
     }
 
     /**
+     *  Is this function node contained within another function node?
+     *  @param iNode - the node of interest.
+     *  @return true if the function node is a closure
+     */
+    public static boolean isFunctionClosure(IFunctionNode functionNode)
+    {
+        IScopedNode containingScope = functionNode.getContainingScope();
+        if (containingScope == null)
+        {
+            return false;
+        }
+        return containingScope.getParent() instanceof IFunctionNode;
+    }
+
+    /**
      *  Is the given node in a class with a base class definition?
      *  @param iNode - the node of interest.
      *  @return true if the node is in a class with a base class.
diff --git a/compiler/src/main/java/org/apache/royale/compiler/problems/ThisUsedInClosureProblem.java b/compiler/src/main/java/org/apache/royale/compiler/problems/ThisUsedInClosureProblem.java
new file mode 100644
index 0000000..8a2dc28
--- /dev/null
+++ b/compiler/src/main/java/org/apache/royale/compiler/problems/ThisUsedInClosureProblem.java
@@ -0,0 +1,40 @@
+/*
+ *
+ *  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.compiler.problems;
+
+import org.apache.royale.compiler.tree.as.IASNode;
+
+/**
+ *  Diagnostic emitted when the method body semantic checker detects
+ *  a reference to "this" in a closure
+ */
+public final class ThisUsedInClosureProblem extends SemanticWarningProblem
+{
+    public static final String DESCRIPTION =
+        "Encountered ${THIS} keyword within closure. Value of ${THIS} will not be the same as enclosing scope.";
+
+    public ThisUsedInClosureProblem(IASNode site)
+    {
+        super(site);
+    }
+
+    // Prevent these from being localized.
+    public final String THIS = "this";
+}