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 7e7b269bc922080e9084f757e3eecfa5c94697b9 Author: Josh Tynjala <joshtynj...@apache.org> AuthorDate: Wed Sep 11 13:18:52 2019 -0700 compiler: warn when using this in a function closure (references #90) --- .../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"; +}