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/11/06 20:56:25 UTC

[royale-compiler] 02/03: report error if we can figure out a local var was used before its declaration. Use of an instance var of the same name as a local var before the local var is declared seems to work ok in SWF but not in JS so we'll report an error

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 c7d26b06d8fb24dac6b8461aee69334bae5cb7e9
Author: Alex Harui <ah...@apache.org>
AuthorDate: Tue Nov 6 12:26:07 2018 -0800

    report error if we can figure out a local var was used before its declaration.  Use of an instance var of the same name as a local var before the local var is declared seems to work ok in SWF but not in JS so we'll report an error
---
 .../internal/codegen/js/goog/JSGoogEmitter.java    | 20 +++++++
 .../VariableUsedBeforeDeclarationProblem.java      | 62 ++++++++++++++++++++++
 2 files changed, 82 insertions(+)

diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogEmitter.java
index d0d55e9..88628d5 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogEmitter.java
@@ -37,6 +37,7 @@ import org.apache.royale.compiler.definitions.IFunctionDefinition;
 import org.apache.royale.compiler.definitions.IPackageDefinition;
 import org.apache.royale.compiler.definitions.ITypeDefinition;
 import org.apache.royale.compiler.definitions.IVariableDefinition;
+import org.apache.royale.compiler.filespecs.IFileSpecification;
 import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
 import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
 import org.apache.royale.compiler.internal.codegen.js.JSEmitter;
@@ -44,14 +45,18 @@ import org.apache.royale.compiler.internal.codegen.js.JSEmitterTokens;
 import org.apache.royale.compiler.internal.codegen.js.JSSessionModel;
 import org.apache.royale.compiler.internal.codegen.js.utils.EmitterUtils;
 import org.apache.royale.compiler.internal.definitions.AccessorDefinition;
+import org.apache.royale.compiler.internal.definitions.ClassDefinition;
 import org.apache.royale.compiler.internal.definitions.FunctionDefinition;
 import org.apache.royale.compiler.internal.definitions.NamespaceDefinition.INamepaceDeclarationDirective;
+import org.apache.royale.compiler.internal.definitions.VariableDefinition;
 import org.apache.royale.compiler.internal.scopes.PackageScope;
 import org.apache.royale.compiler.internal.tree.as.ChainedVariableNode;
 import org.apache.royale.compiler.internal.tree.as.FunctionCallNode;
 import org.apache.royale.compiler.internal.tree.as.FunctionNode;
 import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
+import org.apache.royale.compiler.internal.tree.as.VariableNode;
 import org.apache.royale.compiler.problems.ICompilerProblem;
+import org.apache.royale.compiler.problems.VariableUsedBeforeDeclarationProblem;
 import org.apache.royale.compiler.projects.ICompilerProject;
 import org.apache.royale.compiler.scopes.IASScope;
 import org.apache.royale.compiler.tree.ASTNodeID;
@@ -928,6 +933,21 @@ public class JSGoogEmitter extends JSEmitter implements IJSGoogEmitter
             return;
         }
         IDefinition definition = node.resolve(getWalker().getProject());
+        if (node.getNodeID() == ASTNodeID.IdentifierID && node.getParent().getNodeID() == ASTNodeID.VariableID)
+        {
+        	if (definition instanceof VariableDefinition && (!(definition.getParent() instanceof ClassDefinition)))
+        	{
+        		IFileSpecification defFile = ((VariableDefinition)definition).getFileSpecification();
+        		IFileSpecification varFile = node.getFileSpecification();
+        		if (defFile != null && varFile != null && varFile.equals(defFile))
+        		{
+        			if (node.getAbsoluteStart() < definition.getAbsoluteStart())
+        			{
+        				getProblems().add(new VariableUsedBeforeDeclarationProblem(node, definition.getBaseName()));
+        			}
+        		}
+        	}
+        }
         if (node.getNodeID() == ASTNodeID.ClassReferenceID)
         {
             write(definition.getQualifiedName());
diff --git a/compiler/src/main/java/org/apache/royale/compiler/problems/VariableUsedBeforeDeclarationProblem.java b/compiler/src/main/java/org/apache/royale/compiler/problems/VariableUsedBeforeDeclarationProblem.java
new file mode 100644
index 0000000..56a4102
--- /dev/null
+++ b/compiler/src/main/java/org/apache/royale/compiler/problems/VariableUsedBeforeDeclarationProblem.java
@@ -0,0 +1,62 @@
+/*
+ *
+ *  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;
+
+/**
+ *  Error if we can detect a variable is used before its declaration.
+ *  var foo = bar;
+ *  var bar = 0;
+ *  
+ *  This check is needed when there is also a bar property on the class
+ *  containing the method with the error.
+ *  
+ *  private var bar:int = 0;
+ *  public function baz()
+ *  {
+ *      var foo:int = bar;
+ *      var bar:int = 1;
+ *  }
+ *  
+ *  In the code above, it appears that SWF code will set foo to this.bar.
+ *  I think if a findProp is generated it might know the local variable
+ *  is not in scope?
+ *  But in JS code, foo is set to undefined because at least Safari
+ *  will reference the local variable before it has been initialized.
+ *  
+ *  So, we will generate an error since this code will not work in
+ *  the browser.
+ */
+public final class VariableUsedBeforeDeclarationProblem extends SemanticProblem
+{
+    public static final String DESCRIPTION =
+        "Variable ${declName} used before declaration.";
+
+    public static final int errorCode = 1555;
+
+    public VariableUsedBeforeDeclarationProblem(IASNode site, String declName)
+    {
+        super(site);
+        this.declName = declName;
+    }
+    
+    public final String declName;
+}