You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by ah...@apache.org on 2018/10/29 17:41:25 UTC

[royale-compiler] 01/02: add checks for conflicting definitions and add -allow-private-name-conflicts option. This required adjusting the externs since they had conflicting definitions

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

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

commit 97dc7275c398d86bec6186e02e973ce0e49011bc
Author: Alex Harui <ah...@apache.org>
AuthorDate: Mon Oct 29 00:18:20 2018 -0700

    add checks for conflicting definitions and add -allow-private-name-conflicts option.  This required adjusting the externs since they had conflicting definitions
---
 .../royale/compiler/config/Configuration.java      | 25 ++++++++++++++
 .../royale/compiler/projects/ICompilerProject.java |  5 +++
 .../src/test/config/externc-config.xml             | 28 ++++++++++++++++
 .../codegen/typedefs/TypedefsTestUtils.java        |  7 ++++
 .../royale/compiler/codegen/js/IJSEmitter.java     |  1 +
 .../compiler/internal/codegen/js/JSEmitter.java    |  6 ++++
 .../internal/codegen/js/jx/ClassEmitter.java       |  6 +++-
 .../internal/codegen/js/jx/FieldEmitter.java       |  6 +++-
 .../internal/codegen/js/jx/IdentifierEmitter.java  |  6 +++-
 .../codegen/js/royale/JSRoyaleEmitter.java         |  8 +++--
 .../internal/definitions/FunctionDefinition.java   | 28 +++++++++++++++-
 .../internal/parsing/as/ConfigProcessor.java       |  6 ++++
 .../compiler/internal/projects/ASCProject.java     |  6 ++++
 .../compiler/internal/projects/RoyaleProject.java  | 15 +++++++++
 .../projects/RoyaleProjectConfigurator.java        |  1 +
 .../problems/ConflictingDefinitionProblem.java     | 38 ++++++++++------------
 16 files changed, 166 insertions(+), 26 deletions(-)

diff --git a/compiler-common/src/main/java/org/apache/royale/compiler/config/Configuration.java b/compiler-common/src/main/java/org/apache/royale/compiler/config/Configuration.java
index 40433c9..85f779f 100644
--- a/compiler-common/src/main/java/org/apache/royale/compiler/config/Configuration.java
+++ b/compiler-common/src/main/java/org/apache/royale/compiler/config/Configuration.java
@@ -1460,6 +1460,31 @@ public class Configuration
     }
 
     //
+    // 'compiler.allow-private-name-conflicts' option
+    //
+
+    private boolean allowPrivateNameConflicts = true;
+
+    public boolean getCompilerAllowPrivateNameConflicts()
+    {
+        return allowPrivateNameConflicts;
+    }
+
+    /**
+     * Whether the compiler will allow a subclass to have a variable/property/method with the
+     * same name as a private variable/property/method in the base classes.  The compiler
+     * will always report an error if the subclass has an API that conflicts with public/protected
+     * APIs in the base classes.
+     */
+    @Config
+    @Mapping({ "compiler", "allow-private-name-conflicts" })
+    @RoyaleOnly
+    public void setCompilerAllowPrivateNameConflicts(ConfigurationValue cv, boolean allow)
+    {
+        this.allowPrivateNameConflicts = allow;
+    }
+
+    //
     // 'compiler.actionscript-file-encoding' option
     //
 
diff --git a/compiler-common/src/main/java/org/apache/royale/compiler/projects/ICompilerProject.java b/compiler-common/src/main/java/org/apache/royale/compiler/projects/ICompilerProject.java
index 85fc156..332576a 100644
--- a/compiler-common/src/main/java/org/apache/royale/compiler/projects/ICompilerProject.java
+++ b/compiler-common/src/main/java/org/apache/royale/compiler/projects/ICompilerProject.java
@@ -261,5 +261,10 @@ public interface ICompilerProject
 	boolean isParameterCountMismatchAllowed(
 			IFunctionDefinition functionDefinition, int formalCount,
 			int actualCount);
+	
+    /**
+     * @return True if a subclass can have a private API with the same name as a private API in its base classes.
+     */
+	boolean getAllowPrivateNameConflicts();
 
 }
diff --git a/compiler-externc/src/test/config/externc-config.xml b/compiler-externc/src/test/config/externc-config.xml
index ab2a1c0..3171696 100644
--- a/compiler-externc/src/test/config/externc-config.xml
+++ b/compiler-externc/src/test/config/externc-config.xml
@@ -128,6 +128,34 @@
         <class>String</class>
         <name>raw</name>
     </exclude>
+    <exclude>
+        <class>Document</class>
+        <name>loadXML</name>
+    </exclude>
+    <exclude>
+        <class>Event</class>
+        <name>initUIEvent</name>
+    </exclude>
+    <exclude>
+        <class>Event</class>
+        <name>initMessageEvent</name>
+    </exclude>
+    <exclude>
+        <class>Element</class>
+        <name>load</name>
+    </exclude>
+    <exclude>
+        <class>Document</class>
+        <name>open</name>
+    </exclude>
+    <exclude>
+        <class>Document</class>
+        <name>close</name>
+    </exclude>
+    <exclude>
+        <class>Document</class>
+        <name>createTreeWalker</name>
+    </exclude>
     <!-- SVG -->
     <exclude><class>SVGStylable</class><name>className</name></exclude>
     <exclude><class>SVGStylable</class><name>style</name></exclude>
diff --git a/compiler-externc/src/test/java/org/apache/royale/compiler/internal/codegen/typedefs/TypedefsTestUtils.java b/compiler-externc/src/test/java/org/apache/royale/compiler/internal/codegen/typedefs/TypedefsTestUtils.java
index 3d04b7c..87daab5 100644
--- a/compiler-externc/src/test/java/org/apache/royale/compiler/internal/codegen/typedefs/TypedefsTestUtils.java
+++ b/compiler-externc/src/test/java/org/apache/royale/compiler/internal/codegen/typedefs/TypedefsTestUtils.java
@@ -95,6 +95,13 @@ public class TypedefsTestUtils
         config.addExclude("Date", "valueOf");
         config.addExclude("String", "valueOf");
         config.addExclude("String", "raw");
+        config.addExclude("Document", "loadXML");
+        config.addExclude("Document", "open");
+        config.addExclude("Document", "close");
+        config.addExclude("Document", "createTreeWalker");
+        config.addExclude("Event", "initUIEvent");
+        config.addExclude("Event", "initMessageEvent");
+        config.addExclude("Element", "load");
 
         // SVG
         config.addExclude("SVGStylable", "className");
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/IJSEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/IJSEmitter.java
index ae36a77..5dffb4d 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/IJSEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/IJSEmitter.java
@@ -39,6 +39,7 @@ public interface IJSEmitter extends IASEmitter, IMappingEmitter
     JSSessionModel getModel();
     
     String formatQualifiedName(String name);
+    String formatPrivateName(String className, String name);
     
     void emitSourceMapDirective(ITypeNode node);
     
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java
index bc2649a..ae8768a 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java
@@ -499,4 +499,10 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
         }
     }
 
+	@Override
+	public String formatPrivateName(String className, String name) {
+		// TODO Auto-generated method stub
+		return className.replace(".", "_") + "_" + name;
+	}
+
 }
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ClassEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ClassEmitter.java
index ee80893..6c3ddda 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ClassEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ClassEmitter.java
@@ -244,7 +244,11 @@ public class ClassEmitter extends JSSubEmitter implements
                     writeNewline();
                     write(ASEmitterTokens.THIS);
                     write(ASEmitterTokens.MEMBER_ACCESS);
-                    write(dnode.getName());
+                    String dname = dnode.getName();
+                    IDefinition dDef = dnode.getDefinition();
+                	if (dDef != null && dDef.isPrivate() && getProject().getAllowPrivateNameConflicts())
+                		dname = getEmitter().formatPrivateName(dDef.getParent().getQualifiedName(), dname);
+                    write(dname);
                     if (dnode.getNodeID() == ASTNodeID.BindableVariableID)
                     {
                     	write("_");
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FieldEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FieldEmitter.java
index 13876ca..c9dddc4 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FieldEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FieldEmitter.java
@@ -101,7 +101,11 @@ public class FieldEmitter extends JSSubEmitter implements
             className = getEmitter().formatQualifiedName(definition.getQualifiedName());
             write(className
                     + ASEmitterTokens.MEMBER_ACCESS.getToken() + root);
-            write(node.getName());
+            String qname = node.getName();
+            IDefinition nodeDef = node.getDefinition();
+        	if (nodeDef != null && nodeDef.isPrivate() && getProject().getAllowPrivateNameConflicts())
+        		qname = getEmitter().formatPrivateName(nodeDef.getParent().getQualifiedName(), qname);
+            write(qname);
             endMapping(node.getNameExpressionNode());
         }
 
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/IdentifierEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/IdentifierEmitter.java
index e7e19a8..49fcc0c 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/IdentifierEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/IdentifierEmitter.java
@@ -328,8 +328,12 @@ public class IdentifierEmitter extends JSSubEmitter implements
                 {
                 	write("[\"" + qname + "\"]");                    	
                 }
-                else
+                else 
+                {
+                	if (nodeDef != null && nodeDef.isPrivate() && getProject().getAllowPrivateNameConflicts())
+                		qname = getEmitter().formatPrivateName(nodeDef.getParent().getQualifiedName(), qname);
                     write(qname);
+                }
                 endMapping(node);
             }
             else if (grandparentNodeId == ASTNodeID.E4XFilterID &&
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
index 2171d8e..f258b16 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
@@ -523,13 +523,13 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
     @Override
     public void emitMemberName(IDefinitionNode node)
     {
+        ICompilerProject project = getWalker().getProject();
     	if (node.getNodeID() == ASTNodeID.FunctionID)
     	{
     		FunctionNode fn = (FunctionNode)node;
     		if (isCustomNamespace(fn))
     		{
     			INamespaceDecorationNode ns = ((FunctionNode)node).getActualNamespaceNode();
-                ICompilerProject project = getWalker().getProject();
     			INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(project);
     			formatQualifiedName(nsDef.getQualifiedName()); // register with used names
     			String s = nsDef.getURI();
@@ -537,7 +537,11 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
     			return;
     		}
     	}
-        write(node.getName());
+    	String qname = node.getName();
+    	IDefinition nodeDef = node.getDefinition();
+    	if (nodeDef != null && nodeDef.isPrivate() && project.getAllowPrivateNameConflicts())
+    		qname = formatPrivateName(nodeDef.getParent().getQualifiedName(), qname);
+        write(qname);
     }
 
     @Override
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/FunctionDefinition.java b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/FunctionDefinition.java
index 9ebf0b9..fdcbf80 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/FunctionDefinition.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/FunctionDefinition.java
@@ -43,6 +43,8 @@ import org.apache.royale.compiler.definitions.references.INamespaceReference;
 import org.apache.royale.compiler.definitions.metadata.IMetaTag;
 import org.apache.royale.compiler.definitions.references.IReference;
 import org.apache.royale.compiler.internal.projects.CompilerProject;
+import org.apache.royale.compiler.problems.AmbiguousReferenceProblem;
+import org.apache.royale.compiler.problems.ConflictingDefinitionProblem;
 import org.apache.royale.compiler.projects.ICompilerProject;
 import org.apache.royale.compiler.scopes.IASScope;
 import org.apache.royale.compiler.scopes.IDefinitionSet;
@@ -51,6 +53,8 @@ import org.apache.royale.compiler.tree.as.IContainerNode;
 import org.apache.royale.compiler.tree.as.IDefinitionNode;
 import org.apache.royale.compiler.tree.as.IFunctionNode;
 
+import com.google.common.base.Predicate;
+
 /**
  * Each instance of this class represents the definition of an ActionScript
  * function in the symbol table.
@@ -302,7 +306,11 @@ public class FunctionDefinition extends ScopedDefinitionBase implements IFunctio
             IDefinition baseFunc = base.getContainedScope().getQualifiedPropertyFromDef(
                     project, base, this.getBaseName(), namespace, false);
 
-            return baseFunc instanceof FunctionDefinition ? (FunctionDefinition)baseFunc : null;
+            if (baseFunc instanceof FunctionDefinition) return (FunctionDefinition)baseFunc;
+            
+            IDefinition anyDef = base.getContainedScope().getPropertyFromDef(project, base, this.getBaseName(), new PrivatePredicate(!project.getAllowPrivateNameConflicts()), false);
+            if (anyDef != null) // there might be a variable or a function in a different namespace (private vs protected)
+            	project.getProblems().add(new ConflictingDefinitionProblem(this.getFunctionNode(), this.getBaseName(), anyDef.getParent().getQualifiedName()));
         }
         return null;
     }
@@ -628,4 +636,22 @@ public class FunctionDefinition extends ScopedDefinitionBase implements IFunctio
             sb.append(returnType);
         }
     }
+    
+    private static class PrivatePredicate implements Predicate<IDefinition>
+    {
+        private boolean findPrivates;
+
+        public PrivatePredicate(boolean b)
+        {
+            this.findPrivates = b;
+        }
+
+        @Override
+        public boolean apply(IDefinition definition)
+        {
+        	if (!definition.isPrivate()) return true;
+            return findPrivates;
+        }
+    }
+
 }
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ConfigProcessor.java b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ConfigProcessor.java
index 5966459..3d30c7d 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ConfigProcessor.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ConfigProcessor.java
@@ -153,6 +153,12 @@ public class ConfigProcessor
             removeCompilationUnits(Collections.<ICompilationUnit> singletonList(cu));
 
         }
+
+		@Override
+		public boolean getAllowPrivateNameConflicts() {
+			// TODO Auto-generated method stub
+			return false;
+		}
     }
 
     /**
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/ASCProject.java b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/ASCProject.java
index 209755c..f6b78fa 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/ASCProject.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/ASCProject.java
@@ -74,4 +74,10 @@ public class ASCProject extends CompilerProject implements IASCProject
     {
         return false;
     }
+
+	@Override
+	public boolean getAllowPrivateNameConflicts() {
+		// TODO Auto-generated method stub
+		return false;
+	}
 }
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
index 903889d..e787d6c 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
@@ -2415,6 +2415,21 @@ public class RoyaleProject extends ASProject implements IRoyaleProject, ICompile
         return list;
     }
 
+    private boolean allowPrivateNameConflicts;
+    
+    /**
+     * List of compiler defines so it can be overridden
+     */
+    @Override
+    public boolean getAllowPrivateNameConflicts()
+    {
+    	return allowPrivateNameConflicts;
+    }
+    public void setAllowPrivateNameConflicts(boolean allow)
+    {
+    	allowPrivateNameConflicts = allow;
+    }
+
 	@Override
 	public boolean isPlatformRule(ICSSRule rule) {
 		return true;
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProjectConfigurator.java b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProjectConfigurator.java
index 31295fd..df8d4fa 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProjectConfigurator.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProjectConfigurator.java
@@ -261,6 +261,7 @@ public class RoyaleProjectConfigurator extends Configurator
             project.setProxyBaseClass(configValue);
 
             project.setStrictXML(configuration.isStrictXML());
+            project.setAllowPrivateNameConflicts(configuration.getCompilerAllowPrivateNameConflicts());
             
             DataTranscoder.embedClassName = configuration.getByteArrayEmbedClass();
         }
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/IJSEmitter.java b/compiler/src/main/java/org/apache/royale/compiler/problems/ConflictingDefinitionProblem.java
similarity index 51%
copy from compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/IJSEmitter.java
copy to compiler/src/main/java/org/apache/royale/compiler/problems/ConflictingDefinitionProblem.java
index ae36a77..bf0a91c 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/IJSEmitter.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/problems/ConflictingDefinitionProblem.java
@@ -17,31 +17,29 @@
  *
  */
 
-package org.apache.royale.compiler.codegen.js;
+package org.apache.royale.compiler.problems;
 
-import java.io.Writer;
-
-import org.apache.royale.compiler.codegen.as.IASEmitter;
-import org.apache.royale.compiler.definitions.IDefinition;
-import org.apache.royale.compiler.internal.codegen.js.JSSessionModel;
 import org.apache.royale.compiler.tree.as.IASNode;
-import org.apache.royale.compiler.tree.as.ITypeNode;
-import org.apache.royale.compiler.visitor.IASNodeStrategy;
 
 /**
- * The {@link IJSEmitter} interface allows abstraction between the
- * {@link IASNodeStrategy} and the current output buffer {@link Writer}.
- * 
- * @author Michael Schmalle
+ *  Diagnostic emitted when the code generator detects
+ *  a definition that conflicts with an inherited definition
+ *  from a superclass.
  */
-public interface IJSEmitter extends IASEmitter, IMappingEmitter
+public final class ConflictingDefinitionProblem extends SemanticProblem
 {
-    JSSessionModel getModel();
-    
-    String formatQualifiedName(String name);
-    
-    void emitSourceMapDirective(ITypeNode node);
+    public static final String DESCRIPTION =
+        "A conflict exists with inherited definition ${declName} in class ${className}.";
+
+    public static final int errorCode = 1554;
+
+    public ConflictingDefinitionProblem(IASNode site, String declName, String className)
+    {
+        super(site);
+        this.declName = declName;
+        this.className = className;
+    }
     
-    void emitClosureStart();
-    void emitClosureEnd(IASNode node, IDefinition nodeDef);
+    public final String declName;
+    public final String className;
 }