You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by gr...@apache.org on 2020/02/12 07:43:08 UTC

[royale-compiler] 03/03: Alignment with Flex : added warnings for redundant [Bindable] tags.

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

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

commit 9c2cce648aebf5d147c5c249f21c8b90c4216b3b
Author: greg-dove <gr...@gmail.com>
AuthorDate: Wed Feb 12 19:06:12 2020 +1300

    Alignment with Flex : added warnings for redundant [Bindable] tags.
---
 .../internal/as/codegen/BindableHelper.java        |  37 ++
 .../as/codegen/ClassDirectiveProcessor.java        |  55 +--
 .../problems/RedundantBindableTagProblem.java      |  48 +++
 .../src/test/java/as/ASBindableClassTests.java     | 420 ---------------------
 4 files changed, 118 insertions(+), 442 deletions(-)

diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/BindableHelper.java b/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/BindableHelper.java
index 92ec4a3..73626cb 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/BindableHelper.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/BindableHelper.java
@@ -32,9 +32,12 @@ import org.apache.royale.abc.visitors.ITraitsVisitor;
 import org.apache.royale.compiler.common.DependencyType;
 import org.apache.royale.compiler.constants.IASLanguageConstants;
 import org.apache.royale.compiler.definitions.IDefinition;
+import org.apache.royale.compiler.definitions.metadata.IMetaTag;
 import org.apache.royale.compiler.internal.abc.FunctionGeneratorHelper;
 import org.apache.royale.compiler.internal.definitions.NamespaceDefinition;
 import org.apache.royale.compiler.internal.scopes.ASScope;
+import org.apache.royale.compiler.tree.as.IASNode;
+import org.apache.royale.compiler.tree.as.IDefinitionNode;
 
 import java.util.Vector;
 
@@ -71,6 +74,40 @@ import static org.apache.royale.abc.ABCConstants.TRAIT_Var;
 public class BindableHelper
 {
     /**
+     * Check to see if the metaTag is a codegen style [Bindable] tag (without any event names specified)
+     * @param metaTag
+     * @return true if the tag is [Bindable]
+     */
+    public static boolean isCodeGenBindable(IMetaTag metaTag) {
+        return metaTag != null
+                && metaTag.getTagName().equals(BINDABLE)
+                && metaTag.getAllAttributes().length == 0;
+    }
+
+    /**
+     * A convenience method to get the next full node after all the Metadata tags, for when
+     * a Binding problem should be reported against the main source node for the definition
+     * @param site the full definition with [Bindable]
+     * @return the first node after the MetaData tags
+     */
+    public static IASNode getProblemReportingNode(IDefinition site) {
+        IDefinitionNode siteNode = site.getNode();
+
+        int afterMetas = siteNode.getMetaTags().getAbsoluteEnd();
+
+        int childrenCount = siteNode.getChildCount();
+        IASNode reportingNode = siteNode;
+        for (int i = 1; i < childrenCount; i++) {
+            IASNode nextNode = siteNode.getChild(i);
+            if (nextNode.getAbsoluteStart() > afterMetas) {
+                reportingNode = nextNode;
+                break;
+            }
+        }
+        return reportingNode;
+    }
+
+    /**
      * Generate a synthetic getter for a var that is bindable.  The generated getter will simply return the value of
      * the property.
      * @param classScope    the scope of the class to declare the getter in
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/ClassDirectiveProcessor.java b/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/ClassDirectiveProcessor.java
index 6396887..2f71bfb 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/ClassDirectiveProcessor.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/ClassDirectiveProcessor.java
@@ -787,47 +787,47 @@ class ClassDirectiveProcessor extends DirectiveProcessor
         ICompilerProject project = classScope.getProject();
         ASTUtil.processFunctionNode(func, project);
         boolean isBindable = false;
+
         if (funcDef instanceof AccessorDefinition)
         {
-            IMetaTag[] metaTags = funcDef.getAllMetaTags();
+            boolean isClassBindable = false;
+            IMetaTag[] metaTags = getClassDefinition().getAllMetaTags();
             for (IMetaTag metaTag : metaTags)
             {
-                if (metaTag.getTagName().equals(BindableHelper.BINDABLE))
-                {
-                    IMetaTagAttribute[] attrs = metaTag.getAllAttributes();
-                    isBindable = attrs.length == 0;
+                if (BindableHelper.isCodeGenBindable(metaTag)) {
+                    isClassBindable = true;
+                    break;
+                }
+            }
+            AccessorDefinition definitionWithBindable = null;
+
+            metaTags = funcDef.getAllMetaTags();
+            for (IMetaTag metaTag : metaTags)
+            {
+                if (BindableHelper.isCodeGenBindable(metaTag)) {
+                    isBindable = true;
+                    definitionWithBindable = (AccessorDefinition)funcDef;
+                    break;
                 }
             }
             AccessorDefinition otherDef =
                     ((AccessorDefinition)funcDef).resolveCorrespondingAccessor(classScope.getProject());
             if (!isBindable)
             {
-                // ignore if not in your class def
                 if (otherDef != null && otherDef.getContainingScope().equals(funcDef.getContainingScope()))
                 {
                     metaTags = otherDef.getAllMetaTags();
                     for (IMetaTag metaTag : metaTags)
                     {
-                        if (metaTag.getTagName().equals(BindableHelper.BINDABLE))
-                        {
-                            IMetaTagAttribute[] attrs = metaTag.getAllAttributes();
-                            isBindable = attrs.length == 0;
+                        if (BindableHelper.isCodeGenBindable(metaTag)) {
+                            isBindable = true;
+                            definitionWithBindable = otherDef;
+                            break;
                         }
                     }
                 }
             }
-            if (!isBindable)
-            {
-                metaTags = getClassDefinition().getAllMetaTags();
-                for (IMetaTag metaTag : metaTags)
-                {
-                    if (metaTag.getTagName().equals(BindableHelper.BINDABLE))
-                    {
-                        IMetaTagAttribute[] attrs = metaTag.getAllAttributes();
-                        isBindable = attrs.length == 0;
-                    }
-                }
-            }
+
             if (isBindable
                     && otherDef instanceof ISetterDefinition
                     && !(otherDef.getContainingScope().equals(funcDef.getContainingScope()))) {
@@ -835,6 +835,17 @@ class ClassDirectiveProcessor extends DirectiveProcessor
                 isBindable = false;
                 classScope.addProblem(new BindableGetterCodeGenProblem((IGetterDefinition) funcDef));
             }
+            if (isClassBindable) {
+                if (isBindable) {
+                    if (definitionWithBindable == funcDef) { //if we don't do this, we will end up with two reports
+                        classScope.addProblem(new RedundantBindableTagProblem(
+                                BindableHelper.getProblemReportingNode(definitionWithBindable)
+                        ));
+                    }
+                } else {
+                    isBindable = true;
+                }
+            }
         }
         
         functionSemanticChecks(func);
diff --git a/compiler/src/main/java/org/apache/royale/compiler/problems/RedundantBindableTagProblem.java b/compiler/src/main/java/org/apache/royale/compiler/problems/RedundantBindableTagProblem.java
new file mode 100644
index 0000000..3fc91db
--- /dev/null
+++ b/compiler/src/main/java/org/apache/royale/compiler/problems/RedundantBindableTagProblem.java
@@ -0,0 +1,48 @@
+/*
+ *
+ *  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.common.ISourceLocation;
+import org.apache.royale.compiler.common.SourceLocation;
+import org.apache.royale.compiler.definitions.IDefinition;
+import org.apache.royale.compiler.problems.annotations.DefaultSeverity;
+import org.apache.royale.compiler.tree.as.IASNode;
+import org.apache.royale.compiler.tree.as.IDefinitionNode;
+
+/**
+ * Problem generated when code attempts to bind to something that isn't bindable.
+ */
+@DefaultSeverity(CompilerProblemSeverity.WARNING)
+public final class RedundantBindableTagProblem extends SemanticProblem
+{
+    public static final String DESCRIPTION =
+        "Class already marked [Bindable]; property-level [Bindable] is redundant and will be ignored.";
+
+    public static final int warningCode = 5050;
+
+    /**
+     * @param site should be the identifier node of identifier/thing with the redundant [Bindable] that is causing the problem.
+     */
+    public RedundantBindableTagProblem(IASNode site)
+    {
+        super(site);
+    }
+
+}
diff --git a/compiler/src/test/java/as/ASBindableClassTests.java b/compiler/src/test/java/as/ASBindableClassTests.java
deleted file mode 100644
index c3ccb7a..0000000
--- a/compiler/src/test/java/as/ASBindableClassTests.java
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- *
- *  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 as;
-
-import org.junit.Test;
-
-
-public class ASBindableClassTests extends ASFeatureTestsBase
-{
-    /**
-     * These tests are simply to ensure that Bindable source code variations
-     * that should compile without error do so, and those that should generate
-     * and error also do what they should.
-     * At compiler testing time, it is not possible to test the runtime behaviour of the
-     * generated code, because it depends on framework support and that should be tested
-     * in the framework build. So these tests are just to ensure that various combinations
-     * of Bindable definitions compile successfully or they do not, if they should show an Error level problem.
-     */
-
-    @Test
-    public void testEmptyBindableClass()
-    {
-        String[] imports = new String[]
-        {
-        };
-        String[] declarations = new String[]
-        {
-        };
-        String[] testCode = new String[]
-        {
-        };
-        String[] extra = new String[]
-        {
-            "[Bindable]",
-            " class EmptyBindable {",
-            "}"
-        };
-        String source = getAS(imports, declarations, testCode, extra);
-
-        String[] options = new String[]
-        {
-
-        };
-
-        compileAndRun(source,false, false, false, options);
-    }
-
-    @Test
-    public void testVariableBindable()
-    {
-        String[] imports = new String[]
-                {
-                };
-        String[] declarations = new String[]
-                {
-                };
-        String[] testCode = new String[]
-                {
-                };
-        String[] extra = new String[]
-                {
-                        "[Bindable]",
-                        " class VariableBindable {",
-                        "  public var something:String;",
-                        "}"
-                };
-        String source = getAS(imports, declarations, testCode, extra);
-
-        String[] options = new String[]
-                {
-
-                };
-        //this will compile ok, but is missing the framework dispatcher imports (but the code that would cause a runtime error is never executed)
-        compileAndRun(source,false, false, false, options);
-    }
-
-    @Test
-    public void testGetterSetterBindable()
-    {
-        String[] imports = new String[]
-                {
-                };
-        String[] declarations = new String[]
-                {
-                };
-        String[] testCode = new String[]
-                {
-                };
-        String[] extra = new String[]
-                {
-                        "[Bindable]",
-                        " class GetterSetterBindable {",
-                        "  public function get something():String{" +
-                                "return '';" +
-                            "}",
-                        "  public function set something(value:String):void{" +
-                                "" +
-                                "}",
-                        "}"
-                };
-        String source = getAS(imports, declarations, testCode, extra);
-
-        String[] options = new String[]
-                {
-
-                };
-        //this is only a compilation test: it should compile ok, but is missing the framework dispatcher imports (but the code that would cause a runtime error is never executed)
-        compileAndRun(source,false, false, false, options);
-    }
-
-    @Test
-    public void testEmptyBindableExtendsNonBindable()
-    {
-        String[] imports = new String[]
-                {
-                };
-        String[] declarations = new String[]
-                {
-                };
-        String[] testCode = new String[]
-                {
-                };
-        String[] extra = new String[]
-                {
-                        "class NonBindable{}\n\n",
-
-                        "[Bindable]",
-                        " class EmptyBindableExtendsNonBindable extends NonBindable {",
-                        "}"
-                };
-        String source = getAS(imports, declarations, testCode, extra);
-
-        String[] options = new String[]
-                {
-
-                };
-        //this is only a compilation test: it should compile ok, but is missing the framework dispatcher imports (but the code that would cause a runtime error is never executed)
-        compileAndRun(source,false, false, false, options);
-    }
-
-
-    @Test
-    public void testVarBindableExtendsNonBindable()
-    {
-        String[] imports = new String[]
-                {
-                };
-        String[] declarations = new String[]
-                {
-                };
-        String[] testCode = new String[]
-                {
-                };
-        String[] extra = new String[]
-                {
-                        "class NonBindable{}\n\n",
-
-                        "[Bindable]",
-                        " class VarBindableExtendsNonBindable extends NonBindable {",
-                        "  public var something:String;",
-                        "}"
-                };
-        String source = getAS(imports, declarations, testCode, extra);
-
-        String[] options = new String[]
-                {
-
-                };
-        //this is only a compilation test: it should compile ok, but is missing the framework dispatcher imports (but the code that would cause a runtime error is never executed)
-        compileAndRun(source,false, false, false, options);
-    }
-
-    @Test
-    public void testGetterSetterBindableExtendsNonBindable()
-    {
-        String[] imports = new String[]
-                {
-                };
-        String[] declarations = new String[]
-                {
-                };
-        String[] testCode = new String[]
-                {
-                };
-        String[] extra = new String[]
-                {
-                        "class NonBindable{}\n\n",
-
-                        "[Bindable]",
-                        " class GetterSetterBindableExtendsNonBindable extends NonBindable{",
-                        "  public function get something():String{" +
-                                "return '';" +
-                                "}",
-                        "  public function set something(value:String):void{" +
-                                "" +
-                                "}",
-                        "}"
-                };
-        String source = getAS(imports, declarations, testCode, extra);
-
-        String[] options = new String[]
-                {
-
-                };
-        //this is only a compilation test: it should compile ok, but is missing the framework dispatcher imports (but the code that would cause a runtime error is never executed)
-        compileAndRun(source,false, false, false, options);
-    }
-
-
-    @Test
-    public void testEmptyBindableExtendsEmptyBindable()
-    {
-        String[] imports = new String[]
-                {
-                };
-        String[] declarations = new String[]
-                {
-                };
-        String[] testCode = new String[]
-                {
-                };
-        String[] extra = new String[]
-                {
-                        "[Bindable] class EmptyBindable{}\n\n",
-
-                        "[Bindable]",
-                        " class EmptyBindableExtendsEmptyBindable extends EmptyBindable {",
-                        "}"
-                };
-        String source = getAS(imports, declarations, testCode, extra);
-
-        String[] options = new String[]
-                {
-
-                };
-        //this is only a compilation test: it should compile ok, but is missing the framework dispatcher imports (but the code that would cause a runtime error is never executed)
-        compileAndRun(source,false, false, false, options);
-    }
-
-    @Test
-    public void testVarBindableExtendsEmptyBindable()
-    {
-        String[] imports = new String[]
-                {
-                };
-        String[] declarations = new String[]
-                {
-                };
-        String[] testCode = new String[]
-                {
-                };
-        String[] extra = new String[]
-                {
-                        "[Bindable] class EmptyBindable{}\n\n",
-
-                        "[Bindable]",
-                        " class EmptyBindableExtendsEmptyBindable extends EmptyBindable {",
-                        "  public var something:String;",
-                        "}"
-                };
-        String source = getAS(imports, declarations, testCode, extra);
-
-        String[] options = new String[]
-                {
-
-                };
-        //this is only a compilation test: it should compile ok, but is missing the framework dispatcher imports (but the code that would cause a runtime error is never executed)
-        compileAndRun(source,false, false, false, options);
-    }
-
-    @Test
-    public void  testGetterSetterBindableExtendsEmptyBindable()
-    {
-        String[] imports = new String[]
-                {
-                };
-        String[] declarations = new String[]
-                {
-                };
-        String[] testCode = new String[]
-                {
-                };
-        String[] extra = new String[]
-                {
-                        "[Bindable] class EmptyBindable{}\n\n",
-
-                        "[Bindable]",
-                        " class GetterSetterBindableExtendsEmptyBindable extends EmptyBindable {",
-                        "  public function get something():String{" +
-                                "return '';" +
-                                "}",
-                        "  public function set something(value:String):void{" +
-                                "" +
-                                "}",
-                        "}"
-                };
-        String source = getAS(imports, declarations, testCode, extra);
-
-        String[] options = new String[]
-                {
-
-                };
-        //this is only a compilation test: it should compile ok, but is missing the framework dispatcher imports (but the code that would cause a runtime error is never executed)
-        compileAndRun(source,false, false, false, options);
-    }
-
-
-
-    @Test
-    public void  testGetterSetterBindableExtendsGetterSetterBaseVariation()
-    {
-        String[] imports = new String[]
-                {
-                };
-        String[] declarations = new String[]
-                {
-                };
-        String[] testCode = new String[]
-                {
-                };
-        String[] extra = new String[]
-                {
-                        "class GetterSetterBaseVariation{" +
-                                "    protected var _something:String = 'UnbindableBase_something';\n" +
-                                "    public function get something():String{\n" +
-                                "        return _something;\n" +
-                                "    }\n" +
-                                "\n" +
-                                "\n" +
-                                "    protected var _somethingElse:String = 'UnbindableBase_somethingElse';\n" +
-                                "    public function set somethingElse(value:String):void{\n" +
-                                "        _somethingElse = value;\n" +
-                                "    }" +
-                                "}\n\n",
-
-                        "[Bindable]",
-                        " class GetterSetterBindableExtendsEmptyBindable extends GetterSetterBaseVariation {",
-                        "  public function set something(value:String):void{\n" +
-                                "\t\t\t_something = value;\n" +
-                                "\t\t}",
-                        "}"
-                };
-        String source = getAS(imports, declarations, testCode, extra);
-
-        String[] options = new String[]
-                {
-
-                };
-        //this is only a compilation test: it should compile ok, but is missing the framework dispatcher imports (but the code that would cause a runtime error is never executed)
-        compileAndRun(source,false, false, false, options);
-    }
-
-
-    @Test
-    public void  testGetterSetterBindableExtendsGetterSetterBaseVariation2()
-    {
-        String[] imports = new String[]
-                {
-                };
-        String[] declarations = new String[]
-                {
-                };
-        String[] testCode = new String[]
-                {
-                };
-        String[] extra = new String[]
-                {
-                        "class GetterSetterBaseVariation{" +
-                                "    protected var _something:String = 'UnbindableBase_something';\n" +
-                                "    public function get something():String{\n" +
-                                "        return _something;\n" +
-                                "    }\n" +
-                                "\n" +
-                                "\n" +
-                                "    protected var _somethingElse:String = 'UnbindableBase_somethingElse';\n" +
-                                "    public function set somethingElse(value:String):void{\n" +
-                                "        _somethingElse = value;\n" +
-                                "    }" +
-                                "}\n\n",
-
-                        "[Bindable]",
-                        " class GetterSetterBindableExtendsEmptyBindable extends GetterSetterBaseVariation {",
-                        "\t\tpublic function set something(value:String):void{\n" +
-                                "\t\t\t_something = value;\n" +
-                                "\t\t}",
-                        "\t\tpublic function get somethingElse():String{\n" +
-                                "\t\t\treturn _somethingElse;\n" +
-                                "\t\t}",
-                        "}"
-                };
-        String source = getAS(imports, declarations, testCode, extra);
-
-        String[] options = new String[]
-                {
-
-                };
-
-        //This is 'requires locally defined setter' error in Flex and should also be in royale
-        compileAndExpectErrors(source, false,false,false, options,"[Bindable] on 'somethingElse' getter requires a locally defined setter.\n");
-
-    }
-
-}
\ No newline at end of file