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