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 d8d3b42351f138319758b4c84d67bb100155e7fa
Author: Josh Tynjala <[email protected]>
AuthorDate: Wed May 24 14:51:40 2023 -0700

    New compiler option --infer-types to enable type inference for variables, 
constants, parameters, and return types
    
    If no type is specified, but the variable is assigned in the declaration, 
the type is inferred automatically from the right hand side of the assignment. 
For functions, the return type is inferred from the types of return statements 
(or lack thereof), resolving a common base type, if necessary.
    
    These types are used not only for compile time problem checking, but also 
in the generated ABC bytecode and the generated JS, the same as if the type was 
explicitly declared. This ensures maximum performance (and best optimization by 
Closure Compiler), and maximum productivity in editors and IDEs that use types 
for code intelligence.
    
    Disabled by default and must opt-in to use (we could consider making it 
opt-out in the future, though).
---
 .../royale/compiler/config/Configuration.java      |   18 +
 .../royale/compiler/projects/ICompilerProject.java |    5 +
 .../codegen/js/goog/IJSGoogDocEmitter.java         |    4 +-
 .../internal/codegen/js/goog/JSGoogDocEmitter.java |   69 +-
 .../codegen/js/royale/JSRoyaleDocEmitter.java      |   21 +-
 .../codegen/js/royale/TestRoyaleInferTypes.java    |  584 ++++++
 .../royale/compiler/internal/test/ASTestBase.java  |    7 +
 .../internal/as/codegen/ABCGeneratingReducer.java  |   22 +
 .../internal/definitions/AccessorDefinition.java   |    9 +-
 .../internal/definitions/FunctionDefinition.java   |   17 +
 .../internal/definitions/GetterDefinition.java     |   26 +
 .../internal/definitions/ParameterDefinition.java  |   21 +
 .../internal/definitions/SetterDefinition.java     |   23 +
 .../internal/definitions/VariableDefinition.java   |   21 +
 .../internal/parsing/as/ConfigProcessor.java       |    6 +
 .../compiler/internal/projects/ASCProject.java     |    6 +
 .../compiler/internal/projects/RoyaleProject.java  |   15 +
 .../projects/RoyaleProjectConfigurator.java        |    2 +
 .../semantics/MethodBodySemanticChecker.java       |    8 +
 .../compiler/internal/semantics/SemanticUtils.java |  420 ++++-
 .../compiler/internal/tree/as/ReturnNode.java      |   15 +-
 compiler/src/test/java/as/ASFeatureTestsBase.java  |    7 +
 compiler/src/test/java/as/ASInferTypesTests.java   | 1912 ++++++++++++++++++++
 23 files changed, 3211 insertions(+), 27 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 64b7de260..78e15f8d1 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
@@ -6413,4 +6413,22 @@ public class Configuration
         watch = b;
     }
 
+    //
+    // 'compiler.infer-types'
+    //
+
+    private boolean inferTypes = false;
+
+    public boolean getInferTypes()
+    {
+        return inferTypes;
+    }
+
+    @Config
+    @Mapping({ "compiler", "infer-types" })
+    public void setInferTypes(ConfigurationValue cv, boolean b)
+    {
+        inferTypes = b;
+    }
+
 }
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 0cbd0b53b..ca69ae5e7 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
@@ -286,5 +286,10 @@ public interface ICompilerProject
       * @return True if strict identifier naming is enforced.
       */
      boolean getStrictIdentifierNames();
+     
+     /**
+      * @return True if type inference is enabled.
+      */
+     boolean getInferTypes();
 
 }
diff --git 
a/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/goog/IJSGoogDocEmitter.java
 
b/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/goog/IJSGoogDocEmitter.java
index 33b2afa08..167a7c8eb 100644
--- 
a/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/goog/IJSGoogDocEmitter.java
+++ 
b/compiler-jx/src/main/java/org/apache/royale/compiler/codegen/js/goog/IJSGoogDocEmitter.java
@@ -122,7 +122,7 @@ public interface IJSGoogDocEmitter extends IJSDocEmitter
 
     void emitOverride(IFunctionNode node);
 
-    void emitParam(IParameterNode node, String packageName);
+    void emitParam(IParameterNode node, String packageName, ICompilerProject 
project);
 
     void emitPublic(IASNode node);
 
@@ -132,7 +132,7 @@ public interface IJSGoogDocEmitter extends IJSDocEmitter
 
     void emitInternal(IASNode node);
 
-    void emitReturn(IFunctionNode node, String packageName);
+    void emitReturn(IFunctionNode node, String packageName, ICompilerProject 
project);
 
     void emitThis(ITypeDefinition node, String packageName);
 
diff --git 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogDocEmitter.java
 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogDocEmitter.java
index f5620b53e..75a90c623 100644
--- 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogDocEmitter.java
+++ 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogDocEmitter.java
@@ -200,13 +200,25 @@ public class JSGoogDocEmitter extends JSDocEmitter 
implements IJSGoogDocEmitter
                 }
 
                 IExpressionNode enode = pnode.getNameExpressionNode();
-                emitParam(pnode, enode.resolveType(project).getPackageName());
+                emitParam(pnode, enode.resolveType(project).getPackageName(), 
project);
             }
 
             if (!node.isConstructor())
             {
                 // @return
                 String returnType = node.getReturnType();
+                if (project.getInferTypes() && (returnType == null || 
returnType.isEmpty()))
+                {
+                    ITypeDefinition resolvedTypeDef = 
SemanticUtils.resolveFunctionInferredReturnType(node, project);
+                    if (resolvedTypeDef != null)
+                    {
+                        returnType = resolvedTypeDef.getQualifiedName();
+                    }
+                    else
+                    {
+                        returnType = "*";
+                    }
+                }
                 if (returnType != ""
                         && returnType != ASEmitterTokens.VOID.getToken())
                 {
@@ -217,7 +229,7 @@ public class JSGoogDocEmitter extends JSDocEmitter 
implements IJSGoogDocEmitter
                         hasDoc = true;
                     }
 
-                    emitReturn(node, node.getPackageName());
+                    emitReturn(node, node.getPackageName(), project);
                 }
 
                 // @override
@@ -302,7 +314,7 @@ public class JSGoogDocEmitter extends JSDocEmitter 
implements IJSGoogDocEmitter
     }
 
     @Override
-    public void emitParam(IParameterNode node, String packageName)
+    public void emitParam(IParameterNode node, String packageName, 
ICompilerProject project)
     {
         String postfix = (node.getDefaultValue() == null) ? ""
                 : ASEmitterTokens.EQUAL.getToken();
@@ -315,6 +327,14 @@ public class JSGoogDocEmitter extends JSDocEmitter 
implements IJSGoogDocEmitter
         else
         {
             String typeName = node.getVariableType();
+            if (project.getInferTypes() && typeName.isEmpty())
+            {
+                ITypeDefinition resolvedTypeDef = 
SemanticUtils.resolveVariableInferredType(node, project);
+                if (resolvedTypeDef != null)
+                {
+                    typeName = resolvedTypeDef.getQualifiedName();
+                }
+            }
             if (packageName.length() > 0 && typeName.indexOf(packageName) > -1)
             {
                 String[] parts = typeName.split("\\.");
@@ -355,10 +375,22 @@ public class JSGoogDocEmitter extends JSDocEmitter 
implements IJSGoogDocEmitter
     }
 
     @Override
-    public void emitReturn(IFunctionNode node, String packageName)
+    public void emitReturn(IFunctionNode node, String packageName, 
ICompilerProject project)
     {
         String rtype = node.getReturnType();
-        if (rtype != null)
+        if (project.getInferTypes() && (rtype == null || rtype.isEmpty()))
+        {
+            ITypeDefinition resolvedTypeDef = 
SemanticUtils.resolveFunctionInferredReturnType(node, project);
+            if (resolvedTypeDef != null)
+            {
+                rtype = resolvedTypeDef.getQualifiedName();
+            }
+            else
+            {
+                rtype = "*";
+            }
+        }
+        if (rtype != null && rtype != ASEmitterTokens.VOID.getToken())
         {
             emitJSDocLine(ASEmitterTokens.RETURN,
                     convertASTypeToJS(rtype, packageName));
@@ -374,9 +406,18 @@ public class JSGoogDocEmitter extends JSDocEmitter 
implements IJSGoogDocEmitter
     @Override
     public void emitType(IASNode node, String packageName, ICompilerProject 
project)
     {
-        String type = ((IVariableNode) node).getVariableType();
-        if (((IVariableNode) node).getVariableTypeNode() instanceof 
TypedExpressionNode) {
-            ITypeDefinition elemenTypeDef = 
((TypedExpressionNode)(((IVariableNode) 
node).getVariableTypeNode())).getTypeNode().resolveType(project);
+        IVariableNode varNode = (IVariableNode) node;
+        String type = varNode.getVariableType();
+        if (project.getInferTypes() && type.isEmpty())
+        {
+            ITypeDefinition resolvedTypeDef = 
SemanticUtils.resolveVariableInferredType(varNode, project);
+            if (resolvedTypeDef != null)
+            {
+                type = resolvedTypeDef.getQualifiedName();
+            }
+        }
+        if (varNode.getVariableTypeNode() instanceof TypedExpressionNode) {
+            ITypeDefinition elemenTypeDef = 
((TypedExpressionNode)(varNode.getVariableTypeNode())).getTypeNode().resolveType(project);
             if (elemenTypeDef != null) {
                 type = "Vector.<" +
                         convertASTypeToJS(elemenTypeDef.getQualifiedName(),"")
@@ -395,9 +436,17 @@ public class JSGoogDocEmitter extends JSDocEmitter 
implements IJSGoogDocEmitter
                 convertASTypeToJS(type, packageName));
     }
 
-    public void emitTypeShort(IASNode node, String packageName, 
ICompilerProject project)
+    public void emitTypeShort(IVariableNode node, String packageName, 
ICompilerProject project)
     {
-        String type = ((IVariableNode) node).getVariableType();
+        String type = node.getVariableType();
+        if (project.getInferTypes() && type.isEmpty())
+        {
+            ITypeDefinition resolvedTypeDef = 
SemanticUtils.resolveVariableInferredType(node, project);
+            if (resolvedTypeDef != null)
+            {
+                type = resolvedTypeDef.getQualifiedName();
+            }
+        }
         if (((IVariableNode) node).getVariableTypeNode() instanceof 
TypedExpressionNode) {
             ITypeDefinition elemenTypeDef = 
((TypedExpressionNode)(((IVariableNode) 
node).getVariableTypeNode())).getTypeNode().resolveType(project);
             if (elemenTypeDef != null) {
diff --git 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
index d805eecb2..25861cb9f 100644
--- 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
+++ 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
@@ -41,6 +41,7 @@ import 
org.apache.royale.compiler.internal.codegen.js.goog.JSGoogDocEmitterToken
 import org.apache.royale.compiler.internal.codegen.js.jx.BindableEmitter;
 import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
 import org.apache.royale.compiler.internal.scopes.ASScope;
+import org.apache.royale.compiler.internal.semantics.SemanticUtils;
 import org.apache.royale.compiler.problems.PublicVarWarningProblem;
 import org.apache.royale.compiler.projects.ICompilerProject;
 import org.apache.royale.compiler.tree.ASTNodeID;
@@ -304,7 +305,7 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
                        if (tdef == null)
                            continue;
        
-                       emitParam(pnode, 
project.getActualPackageName(tdef.getPackageName()));
+                       emitParam(pnode, 
project.getActualPackageName(tdef.getPackageName()), project);
                    }
             }
             
@@ -314,6 +315,18 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
                {
                        // @return
                        String returnType = node.getReturnType();
+                    if (project.getInferTypes() && (returnType == null || 
returnType.isEmpty()))
+                    {
+                        ITypeDefinition resolvedTypeDef = 
SemanticUtils.resolveFunctionInferredReturnType(node, project);
+                        if (resolvedTypeDef != null)
+                        {
+                            returnType = resolvedTypeDef.getQualifiedName();
+                        }
+                        else
+                        {
+                            returnType = "*";
+                        }
+                    }
                        if (returnType != ""
                                && returnType != 
ASEmitterTokens.VOID.getToken())
                        {
@@ -334,7 +347,7 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
                            String packageName = "";
                            packageName = tdef != null ? tdef.getPackageName() 
: "";
        
-                           emitReturn(node, 
project.getActualPackageName(packageName));
+                           emitReturn(node, 
project.getActualPackageName(packageName), project);
                        }
                }
                
@@ -500,7 +513,7 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
             ITypeDefinition tdef = ((IFunctionDefinition) node.getDefinition())
                     .resolveReturnType(project);
 
-            emitReturn((IFunctionNode) node, tdef.getPackageName());
+            emitReturn((IFunctionNode) node, tdef.getPackageName(), project);
         }
 
         IParameterNode[] parameters = ((IFunctionNode) node)
@@ -517,7 +530,7 @@ public class JSRoyaleDocEmitter extends JSGoogDocEmitter
             }
 
             IExpressionNode enode = pnode.getNameExpressionNode();
-            emitParam(pnode, enode.resolveType(project).getPackageName());
+            emitParam(pnode, enode.resolveType(project).getPackageName(), 
project);
         }
 
         if (hasDoc)
diff --git 
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleInferTypes.java
 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleInferTypes.java
new file mode 100644
index 000000000..c30ba199a
--- /dev/null
+++ 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleInferTypes.java
@@ -0,0 +1,584 @@
+/*
+ *
+ *  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.internal.codegen.js.royale;
+
+import org.apache.royale.compiler.driver.IBackend;
+import org.apache.royale.compiler.internal.driver.js.goog.JSGoogConfiguration;
+import org.apache.royale.compiler.internal.driver.js.royale.RoyaleBackend;
+import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
+import org.apache.royale.compiler.internal.test.ASTestBase;
+import org.apache.royale.compiler.tree.as.IASNode;
+import org.apache.royale.compiler.tree.as.IClassNode;
+import org.apache.royale.compiler.tree.as.IFileNode;
+import org.apache.royale.compiler.tree.as.IFunctionNode;
+import org.apache.royale.compiler.tree.as.IGetterNode;
+import org.apache.royale.compiler.tree.as.ISetterNode;
+import org.apache.royale.compiler.tree.as.IVariableNode;
+import org.junit.Test;
+
+public class TestRoyaleInferTypes extends ASTestBase
+{
+       @Override
+       public void setUp()
+       {
+               backend = createBackend();
+               project = new RoyaleJSProject(workspace, backend);
+               project.setInferTypes(true);
+               project.config = new JSGoogConfiguration();
+               super.setUp();
+       }
+
+       // ----- local variables
+
+       @Test
+       public void testInferLocalVariableWithStringDefaultValue()
+       {
+               IVariableNode node = getVariable("var s = \"hello\"");
+               asBlockWalker.visitVariable(node);
+               assertOut("var /** @type {string} */ s = \"hello\"");
+       }
+
+       @Test
+       public void testInferLocalVariableWithBooleanDefaultValue()
+       {
+               IVariableNode node = getVariable("var b = true");
+               asBlockWalker.visitVariable(node);
+               assertOut("var /** @type {boolean} */ b = true");
+       }
+
+       @Test
+       public void testInferLocalVariableWithNumberDefaultValue()
+       {
+               IVariableNode node = getVariable("var n = 123.4");
+               asBlockWalker.visitVariable(node);
+               assertOut("var /** @type {number} */ n = 123.4");
+       }
+
+       @Test
+       public void testInferLocalVariableWithArrayDefaultValue()
+       {
+               IVariableNode node = getVariable("var a = []");
+               asBlockWalker.visitVariable(node);
+               assertOut("var /** @type {Array} */ a = []");
+       }
+
+       @Test
+       public void testInferLocalVariableWithObjectDefaultValue()
+       {
+               IVariableNode node = getVariable("var o = {}");
+               asBlockWalker.visitVariable(node);
+               assertOut("var /** @type {Object} */ o = {}");
+       }
+
+       @Test
+       public void testInferLocalVariableWithDateDefaultValue()
+       {
+               IVariableNode node = getVariable("var d = new Date();");
+               asBlockWalker.visitVariable(node);
+               assertOut("var /** @type {Date} */ d = new Date()");
+       }
+
+       @Test
+       public void testInferLocalVariableWithNullDefaultValue()
+       {
+               IVariableNode node = getVariable("var x = null;");
+               asBlockWalker.visitVariable(node);
+               assertOut("var /** @type {*} */ x = null");
+       }
+
+       @Test
+       public void testInferLocalVariableWithUndefinedDefaultValue()
+       {
+               IVariableNode node = getVariable("var x = undefined;");
+               asBlockWalker.visitVariable(node);
+               assertOut("var /** @type {*} */ x = undefined");
+       }
+
+       @Test
+       public void testInferLocalVariableWithNoDefaultValue()
+       {
+               IVariableNode node = getVariable("var x;");
+               asBlockWalker.visitVariable(node);
+               assertOut("var /** @type {*} */ x");
+       }
+
+       // ----- parameters
+
+       @Test
+       public void testInferParameterWithStringDefaultValue()
+       {
+               IFunctionNode node = getMethod("function f(s = \"hello\"):void 
{}");
+               asBlockWalker.visitFunction(node);
+               assertOut("/**\n * @param {string=} s\n 
*/\nRoyaleTest_A.prototype.f = function(s) {\n  s = typeof s !== 'undefined' ? 
s : \"hello\";\n}");
+       }
+
+       @Test
+       public void testInferParameterWithNullDefaultValue()
+       {
+               IFunctionNode node = getMethod("function f(x = null):void {}");
+               asBlockWalker.visitFunction(node);
+               assertOut("/**\n * @param {*=} x\n */\nRoyaleTest_A.prototype.f 
= function(x) {\n  x = typeof x !== 'undefined' ? x : null;\n}");
+       }
+
+       @Test
+       public void testInferParameterWithUndefinedDefaultValue()
+       {
+               IFunctionNode node = getMethod("function f(x = undefined):void 
{}");
+               asBlockWalker.visitFunction(node);
+               assertOut("/**\n * @param {*=} x\n */\nRoyaleTest_A.prototype.f 
= function(x) {\n  x = typeof x !== 'undefined' ? x : undefined;\n}");
+       }
+
+       @Test
+       public void testInferParameterWithNoDefaultValue()
+       {
+               IFunctionNode node = getMethod("function f(x):void {}");
+               asBlockWalker.visitFunction(node);
+               assertOut("/**\n * @param {*} x\n */\nRoyaleTest_A.prototype.f 
= function(x) {\n}");
+       }
+
+       // ----- returns
+
+       @Test
+       public void testInferReturnWithStringDefaultValue()
+       {
+               IFunctionNode node = getMethod("function f() { return \"hello\" 
}");
+               asBlockWalker.visitFunction(node);
+               assertOut("/**\n * @return {string}\n 
*/\nRoyaleTest_A.prototype.f = function() {\n  return \"hello\";\n}");
+       }
+
+       @Test
+       public void testInferReturnWithNoReturnStatements()
+       {
+               IFunctionNode node = getMethod("function f() {}");
+               asBlockWalker.visitFunction(node);
+               // inferred as void, so no comment is required
+               assertOut("RoyaleTest_A.prototype.f = function() {\n}");
+       }
+
+       @Test
+       public void testInferReturnWithEmptyReturnStatement()
+       {
+               IFunctionNode node = getMethod("function f() { return; }");
+               asBlockWalker.visitFunction(node);
+               // inferred as void, so no comment is required
+               assertOut("RoyaleTest_A.prototype.f = function() {\n  
return;\n}");
+       }
+
+       @Test
+       public void testInferReturnWithNullDefaultValue()
+       {
+               IFunctionNode node = getMethod("function f() { return null; }");
+               asBlockWalker.visitFunction(node);
+               assertOut("/**\n * @return {*}\n */\nRoyaleTest_A.prototype.f = 
function() {\n  return null;\n}");
+       }
+
+       @Test
+       public void testInferReturnWithUndefinedDefaultValue()
+       {
+               IFunctionNode node = getMethod("function f() { return 
undefined; }");
+               asBlockWalker.visitFunction(node);
+               assertOut("/**\n * @return {*}\n */\nRoyaleTest_A.prototype.f = 
function() {\n  return undefined;\n}");
+       }
+
+       @Test
+       public void testInferReturnWithOverrideAndSuperInferredReturn()
+       {
+               IFileNode node = compileAS(
+                       "package { public class A {} }\n" + 
+                       "class C { public function s() { return \"hello\"; } 
}\n" +
+                       "class D extends C { override public function s() { 
return null; } }");
+               IClassNode d = null;
+               for(int i = 0; i < node.getChildCount(); i++)
+               {
+                       IASNode child = node.getChild(i);
+                       if (child instanceof IClassNode)
+                       {
+                               IClassNode childClass = (IClassNode) child;
+                               if ("D".equals(childClass.getName()))
+                               {
+                                       d = childClass;
+                                       break;
+                               }
+                       }
+               }
+               asBlockWalker.visitClass(d);
+               // overrides don't need to specify type
+               assertOut("/**\n * @constructor\n * @extends {C}\n */\nD = 
function() {\n  D.base(this, 'constructor');\n};\ngoog.inherits(D, 
C);\n\n\n/**\n * @override\n */\nD.prototype.s = function() {\n  return 
null;\n};");
+       }
+
+       @Test
+       public void testInferReturnWithOverrideAndSuperDeclaredReturn()
+       {
+               IFileNode node = compileAS(
+                       "package { public class A {} }\n" + 
+                       "class C { public function s():String { return null; } 
}\n" +
+                       "class D extends C { override public function s() { 
return null; } }");
+               IClassNode d = null;
+               for(int i = 0; i < node.getChildCount(); i++)
+               {
+                       IASNode child = node.getChild(i);
+                       if (child instanceof IClassNode)
+                       {
+                               IClassNode childClass = (IClassNode) child;
+                               if ("D".equals(childClass.getName()))
+                               {
+                                       d = childClass;
+                                       break;
+                               }
+                       }
+               }
+               asBlockWalker.visitClass(d);
+               // overrides don't need to specify type
+               assertOut("/**\n * @constructor\n * @extends {C}\n */\nD = 
function() {\n  D.base(this, 'constructor');\n};\ngoog.inherits(D, 
C);\n\n\n/**\n * @override\n */\nD.prototype.s = function() {\n  return 
null;\n};");
+       }
+
+       // ----- member variables
+
+       @Test
+       public void testInferMemberVariableWithStringDefaultValue()
+       {
+               IVariableNode node = getField("public var s = \"hello\"");
+               asBlockWalker.visitVariable(node);
+               assertOut("/**\n * @type {string}\n 
*/\nRoyaleTest_A.prototype.s = \"hello\"");
+       }
+
+       @Test
+       public void testInferMemberVariableWithNullDefaultValue()
+       {
+               IVariableNode node = getField("public var s = null");
+               asBlockWalker.visitVariable(node);
+               assertOut("/**\n * @type {*}\n */\nRoyaleTest_A.prototype.s = 
null");
+       }
+
+       @Test
+       public void testInferMemberVariableWithUndefinedDefaultValue()
+       {
+               IVariableNode node = getField("public var s = undefined");
+               asBlockWalker.visitVariable(node);
+               assertOut("/**\n * @type {*}\n */\nRoyaleTest_A.prototype.s = 
undefined");
+       }
+
+       @Test
+       public void testInferMemberVariableWithNoDefaultValue()
+       {
+               IVariableNode node = getField("public var s");
+               asBlockWalker.visitVariable(node);
+               assertOut("/**\n * @type {*}\n */\nRoyaleTest_A.prototype.s = 
undefined");
+       }
+
+       // ----- static variables
+
+       @Test
+       public void testInferStaticVariableWithStringDefaultValue()
+       {
+               IVariableNode node = getField("public static var s = 
\"hello\"");
+               asBlockWalker.visitVariable(node);
+               assertOut("/**\n * @nocollapse\n * @type {string}\n 
*/\nRoyaleTest_A.s = \"hello\"");
+       }
+
+       @Test
+       public void testInferStaticVariableWithNullDefaultValue()
+       {
+               IVariableNode node = getField("public static var s = null");
+               asBlockWalker.visitVariable(node);
+               assertOut("/**\n * @nocollapse\n * @type {*}\n 
*/\nRoyaleTest_A.s = null");
+       }
+
+       @Test
+       public void testInferStaticVariableWithUndefinedDefaultValue()
+       {
+               IVariableNode node = getField("public static var s = 
undefined");
+               asBlockWalker.visitVariable(node);
+               assertOut("/**\n * @nocollapse\n * @type {*}\n 
*/\nRoyaleTest_A.s = undefined");
+       }
+
+       @Test
+       public void testInferStaticVariableWithNoDefaultValue()
+       {
+               IVariableNode node = getField("public static var s");
+               asBlockWalker.visitVariable(node);
+               assertOut("/**\n * @nocollapse\n * @type {*}\n 
*/\nRoyaleTest_A.s = undefined");
+       }
+
+       // ----- static constants
+
+       @Test
+       public void testInferStaticConstantWithStringDefaultValue()
+       {
+               IVariableNode node = getField("public static const s = 
\"hello\"");
+               asBlockWalker.visitVariable(node);
+               assertOut("/**\n * @nocollapse\n * @const\n * @type {string}\n 
*/\nRoyaleTest_A.s = \"hello\"");
+       }
+
+       @Test
+       public void testInferStaticConstantWithNullDefaultValue()
+       {
+               IVariableNode node = getField("public static const s = null");
+               asBlockWalker.visitVariable(node);
+               assertOut("/**\n * @nocollapse\n * @const\n * @type {*}\n 
*/\nRoyaleTest_A.s = null");
+       }
+
+       @Test
+       public void testInferStaticConstantWithUndefinedDefaultValue()
+       {
+               IVariableNode node = getField("public static const s = 
undefined");
+               asBlockWalker.visitVariable(node);
+               assertOut("/**\n * @nocollapse\n * @const\n * @type {*}\n 
*/\nRoyaleTest_A.s = undefined");
+       }
+
+       @Test
+       public void testInferStaticConstantWithNoDefaultValue()
+       {
+               IVariableNode node = getField("public static const s");
+               asBlockWalker.visitVariable(node);
+               assertOut("/**\n * @nocollapse\n * @const\n * @type {*}\n 
*/\nRoyaleTest_A.s = undefined");
+       }
+
+       // ----- member constants
+
+       @Test
+       public void testInferMemberConstantWithStringDefaultValue()
+       {
+               IVariableNode node = getField("public const s = \"hello\"");
+               asBlockWalker.visitVariable(node);
+               assertOut("/**\n * @const\n * @type {string}\n 
*/\nRoyaleTest_A.prototype.s = \"hello\"");
+       }
+
+       @Test
+       public void testInferMemberConstantWithNullDefaultValue()
+       {
+               IVariableNode node = getField("public const s = null");
+               asBlockWalker.visitVariable(node);
+               assertOut("/**\n * @const\n * @type {*}\n 
*/\nRoyaleTest_A.prototype.s = null");
+       }
+
+       @Test
+       public void testInferMemberConstantWithUndefinedDefaultValue()
+       {
+               IVariableNode node = getField("public const s = undefined");
+               asBlockWalker.visitVariable(node);
+               assertOut("/**\n * @const\n * @type {*}\n 
*/\nRoyaleTest_A.prototype.s = undefined");
+       }
+
+       @Test
+       public void testInferMemberConstantWithNoDefaultValue()
+       {
+               IVariableNode node = getField("public const s");
+               asBlockWalker.visitVariable(node);
+               assertOut("/**\n * @const\n * @type {*}\n 
*/\nRoyaleTest_A.prototype.s = undefined");
+       }
+
+       // ----- local constants
+
+       @Test
+       public void testInferLocalConstantWithStringDefaultValue()
+       {
+               IVariableNode node = getVariable("const s = \"hello\"");
+               asBlockWalker.visitVariable(node);
+               assertOut("\n/**\n * @const\n * @type {string}\n */\nvar s = 
\"hello\"");
+       }
+
+       @Test
+       public void testInferLocalConstantWithNullDefaultValue()
+       {
+               IVariableNode node = getVariable("const s = null");
+               asBlockWalker.visitVariable(node);
+               assertOut("\n/**\n * @const\n * @type {*}\n */\nvar s = null");
+       }
+
+       @Test
+       public void testInferLocalConstantWithUndefinedDefaultValue()
+       {
+               IVariableNode node = getVariable("const s = undefined");
+               asBlockWalker.visitVariable(node);
+               assertOut("\n/**\n * @const\n * @type {*}\n */\nvar s = 
undefined");
+       }
+
+       @Test
+       public void testInferLocalConstantWithNoDefaultValue()
+       {
+               IVariableNode node = getVariable("const s");
+               asBlockWalker.visitVariable(node);
+               assertOut("\n/**\n * @const\n * @type {*}\n */\nvar s");
+       }
+
+       // ----- getters and setters
+
+       @Test
+       public void testInferGetterWithStringDefaultValue()
+       {
+               IGetterNode node = (IGetterNode) getAccessor("public function 
get s() { return \"hello\"; }");
+               asBlockWalker.visitFunction(node);
+               assertOut("/**\n * @return {string}\n 
*/\nRoyaleTest_A.prototype.s = function() {\n  return \"hello\";\n}");
+       }
+
+       @Test
+       public void testInferGetterWithNullDefaultValue()
+       {
+               IGetterNode node = (IGetterNode) getAccessor("public function 
get s() { return null; }");
+               asBlockWalker.visitFunction(node);
+               assertOut("/**\n * @return {*}\n */\nRoyaleTest_A.prototype.s = 
function() {\n  return null;\n}");
+       }
+
+       @Test
+       public void testInferGetterWithUndefinedDefaultValue()
+       {
+               IGetterNode node = (IGetterNode) getAccessor("public function 
get s() { return undefined; }");
+               asBlockWalker.visitFunction(node);
+               assertOut("/**\n * @return {*}\n */\nRoyaleTest_A.prototype.s = 
function() {\n  return undefined;\n}");
+       }
+
+       @Test
+       public void testInferGetterWithSetterDeclaredType()
+       {
+               IClassNode node = getClassNode("class C { public function get 
s() { return null; } public function set s(value:String):void {} }");
+               asBlockWalker.visitClass(node);
+               assertOut("/**\n * @constructor\n */\nC = function() 
{\n};\n\n\n/**\n * @nocollapse\n * @export\n * @type {string}\n 
*/\nC.prototype.s;\n\n\nC.prototype.get__s = function() {\n  return 
null;\n};\n\n\nC.prototype.set__s = function(value) 
{\n};\n\n\nObject.defineProperties(C.prototype, /** @lends {C.prototype} */ 
{\n/**\n * @type {string}\n */\ns: {\nget: C.prototype.get__s,\nset: 
C.prototype.set__s}}\n);");
+       }
+
+       @Test
+       public void testInferSetterWithGetterDeclaredType()
+       {
+               IClassNode node = getClassNode("class C { public function get 
s():String { return null; } public function set s(value):void {} }");
+               asBlockWalker.visitClass(node);
+               assertOut("/**\n * @constructor\n */\nC = function() 
{\n};\n\n\n/**\n * @nocollapse\n * @export\n * @type {string}\n 
*/\nC.prototype.s;\n\n\nC.prototype.get__s = function() {\n  return 
null;\n};\n\n\nC.prototype.set__s = function(value) 
{\n};\n\n\nObject.defineProperties(C.prototype, /** @lends {C.prototype} */ 
{\n/**\n * @type {string}\n */\ns: {\nget: C.prototype.get__s,\nset: 
C.prototype.set__s}}\n);");
+       }
+
+       @Test
+       public void testInferSetterWithGetterStringDefaultValue()
+       {
+               IClassNode node = getClassNode("class C { public function get 
s() { return \"hello\"; } public function set s(value):void {} }");
+               asBlockWalker.visitClass(node);
+               assertOut("/**\n * @constructor\n */\nC = function() 
{\n};\n\n\n/**\n * @nocollapse\n * @export\n * @type {string}\n 
*/\nC.prototype.s;\n\n\nC.prototype.get__s = function() {\n  return 
\"hello\";\n};\n\n\nC.prototype.set__s = function(value) 
{\n};\n\n\nObject.defineProperties(C.prototype, /** @lends {C.prototype} */ 
{\n/**\n * @type {string}\n */\ns: {\nget: C.prototype.get__s,\nset: 
C.prototype.set__s}}\n);");
+       }
+
+       @Test
+       public void testInferSetterWithNoDefaultValue()
+       {
+               ISetterNode node = (ISetterNode) getAccessor("public function 
set s(value) {}");
+               asBlockWalker.visitFunction(node);
+               assertOut("/**\n * @param {*} value\n 
*/\nRoyaleTest_A.prototype.s = function(value) {\n}");
+       }
+
+       @Test
+       public void testInferGetterWithOverrideAndSuperInferredReturn()
+       {
+               IFileNode node = compileAS(
+                       "package { public class A {} }\n" + 
+                       "class C { public function get s() { return \"hello\"; 
} }\n" +
+                       "class D extends C { override public function get s() { 
return null; } }");
+               IClassNode d = null;
+               for(int i = 0; i < node.getChildCount(); i++)
+               {
+                       IASNode child = node.getChild(i);
+                       if (child instanceof IClassNode)
+                       {
+                               IClassNode childClass = (IClassNode) child;
+                               if ("D".equals(childClass.getName()))
+                               {
+                                       d = childClass;
+                                       break;
+                               }
+                       }
+               }
+               asBlockWalker.visitClass(d);
+               assertOut("/**\n * @constructor\n * @extends {C}\n */\nD = 
function() {\n  D.base(this, 'constructor');\n};\ngoog.inherits(D, 
C);\n\n\nD.prototype.get__s = function() {\n  return 
null;\n};\n\n\nObject.defineProperties(D.prototype, /** @lends {D.prototype} */ 
{\n/**\n * @type {string}\n */\ns: {\nget: D.prototype.get__s}}\n);");
+       }
+
+       @Test
+       public void testInferGetterWithOverrideAndSuperDeclaredReturn()
+       {
+               IFileNode node = compileAS(
+                       "package { public class A {} }\n" + 
+                       "class C { public function get s():String { return 
null; } }\n" +
+                       "class D extends C { override public function get s() { 
return null; } }");
+               IClassNode d = null;
+               for(int i = 0; i < node.getChildCount(); i++)
+               {
+                       IASNode child = node.getChild(i);
+                       if (child instanceof IClassNode)
+                       {
+                               IClassNode childClass = (IClassNode) child;
+                               if ("D".equals(childClass.getName()))
+                               {
+                                       d = childClass;
+                                       break;
+                               }
+                       }
+               }
+               asBlockWalker.visitClass(d);
+               assertOut("/**\n * @constructor\n * @extends {C}\n */\nD = 
function() {\n  D.base(this, 'constructor');\n};\ngoog.inherits(D, 
C);\n\n\nD.prototype.get__s = function() {\n  return 
null;\n};\n\n\nObject.defineProperties(D.prototype, /** @lends {D.prototype} */ 
{\n/**\n * @type {string}\n */\ns: {\nget: D.prototype.get__s}}\n);");
+       }
+
+       @Test
+       public void testInferSetterWithOverrideAndSuperInferredType()
+       {
+               IFileNode node = compileAS(
+                       "package { public class A {} }\n" + 
+                       "class C { public function get s():String {} public 
function set s(p) {} }\n" +
+                       "class D extends C { override public function set s(p) 
{} }");
+               IClassNode d = null;
+               for(int i = 0; i < node.getChildCount(); i++)
+               {
+                       IASNode child = node.getChild(i);
+                       if (child instanceof IClassNode)
+                       {
+                               IClassNode childClass = (IClassNode) child;
+                               if ("D".equals(childClass.getName()))
+                               {
+                                       d = childClass;
+                                       break;
+                               }
+                       }
+               }
+               asBlockWalker.visitClass(d);
+               assertOut("/**\n * @constructor\n * @extends {C}\n */\nD = 
function() {\n  D.base(this, 'constructor');\n};\ngoog.inherits(D, 
C);\n\n\nD.prototype.set__s = function(p) 
{\n};\n\n\nObject.defineProperties(D.prototype, /** @lends {D.prototype} */ 
{\n/**\n * @type {string}\n */\ns: {\nget: C.prototype.get__s,\nset: 
D.prototype.set__s}}\n);");
+       }
+
+       @Test
+       public void testInferSetterWithOverrideAndSuperDeclaredType()
+       {
+               IFileNode node = compileAS(
+                       "package { public class A {} }\n" + 
+                       "class C { public function set s(p:String) {} }\n" +
+                       "class D extends C { override public function set s(p) 
{} }");
+               IClassNode d = null;
+               for(int i = 0; i < node.getChildCount(); i++)
+               {
+                       IASNode child = node.getChild(i);
+                       if (child instanceof IClassNode)
+                       {
+                               IClassNode childClass = (IClassNode) child;
+                               if ("D".equals(childClass.getName()))
+                               {
+                                       d = childClass;
+                                       break;
+                               }
+                       }
+               }
+               asBlockWalker.visitClass(d);
+               assertOut("/**\n * @constructor\n * @extends {C}\n */\nD = 
function() {\n  D.base(this, 'constructor');\n};\ngoog.inherits(D, 
C);\n\n\nD.prototype.set__s = function(p) 
{\n};\n\n\nObject.defineProperties(D.prototype, /** @lends {D.prototype} */ 
{\n/**\n * @type {string}\n */\ns: {\nset: D.prototype.set__s}}\n);");
+       }
+
+    protected IBackend createBackend()
+    {
+        return new RoyaleBackend();
+    }
+}
\ No newline at end of file
diff --git 
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/test/ASTestBase.java
 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/test/ASTestBase.java
index 807c950c4..5c8116b46 100644
--- 
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/test/ASTestBase.java
+++ 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/test/ASTestBase.java
@@ -26,6 +26,7 @@ import 
org.apache.royale.compiler.internal.driver.as.ASBackend;
 import org.apache.royale.compiler.tree.as.IASNode;
 import org.apache.royale.compiler.tree.as.IAccessorNode;
 import org.apache.royale.compiler.tree.as.IBinaryOperatorNode;
+import org.apache.royale.compiler.tree.as.IClassNode;
 import org.apache.royale.compiler.tree.as.IDynamicAccessNode;
 import org.apache.royale.compiler.tree.as.IExpressionNode;
 import org.apache.royale.compiler.tree.as.IFileNode;
@@ -134,6 +135,12 @@ public class ASTestBase extends TestBase
         return findFirstDescendantOfType(node, type);
     }
 
+    protected IClassNode getClassNode(String code)
+    {
+        return (IClassNode) getNode(code, IClassNode.class,
+                WRAP_LEVEL_PACKAGE);
+    }
+
     protected IInterfaceNode getInterfaceNode(String code)
     {
         return (IInterfaceNode) getNode(code, IInterfaceNode.class,
diff --git 
a/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/ABCGeneratingReducer.java
 
b/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/ABCGeneratingReducer.java
index b4eb1cff8..42209b662 100644
--- 
a/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/ABCGeneratingReducer.java
+++ 
b/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/ABCGeneratingReducer.java
@@ -89,6 +89,7 @@ import org.apache.royale.compiler.tree.as.IScopedNode;
 import org.apache.royale.compiler.tree.as.ITryNode;
 import org.apache.royale.compiler.tree.as.ITypedExpressionNode;
 import org.apache.royale.compiler.tree.as.IUnaryOperatorNode;
+import org.apache.royale.compiler.tree.as.IVariableNode;
 import org.apache.royale.compiler.tree.as.IWhileLoopNode;
 import org.apache.royale.compiler.tree.as.IWithNode;
 import 
org.apache.royale.compiler.tree.as.ILanguageIdentifierNode.LanguageIdentifierKind;
@@ -5542,9 +5543,30 @@ public class ABCGeneratingReducer
             final Nsset qualifiers = SemanticUtils.getOpenNamespaces(iNode, 
project);
             final Name name = new Name(CONSTANT_Multiname, qualifiers, null);
             result = new Binding(iNode, name, identifier.resolve(project));
+            return result;
         }
         else
         {
+            if (currentScope.getProject().getInferTypes()
+                    && identifier.isImplicit()
+                    && 
identifier.getName().equals(IASLanguageConstants.ANY_TYPE))
+            {
+                IASNode parentNode = identifier.getParent();
+                if (parentNode instanceof IVariableNode)
+                {
+                    IVariableNode varNode = (IVariableNode) parentNode;
+                    if (identifier.equals(varNode.getVariableTypeNode()))
+                    {
+                        ITypeDefinition typeDef = 
SemanticUtils.resolveVariableInferredType(varNode, currentScope.getProject());
+                        if (typeDef != null)
+                        {
+                            final Name name = new Name(new 
Namespace(CONSTANT_PackageNs, typeDef.getPackageName()), typeDef.getBaseName());
+                            result = new Binding(iNode, name, typeDef);
+                            return result;
+                        }
+                    }
+                }
+            }
             result = currentScope.resolveName(identifier);
             currentScope.getMethodBodySemanticChecker().checkSimpleName(iNode, 
result);
         }
diff --git 
a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/AccessorDefinition.java
 
b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/AccessorDefinition.java
index f842087b6..286bfac3d 100644
--- 
a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/AccessorDefinition.java
+++ 
b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/AccessorDefinition.java
@@ -21,7 +21,6 @@ package org.apache.royale.compiler.internal.definitions;
 
 import java.util.Iterator;
 
-
 import org.apache.royale.compiler.definitions.IAccessorDefinition;
 import org.apache.royale.compiler.definitions.IClassDefinition;
 import org.apache.royale.compiler.definitions.IDefinition;
@@ -30,16 +29,16 @@ import 
org.apache.royale.compiler.definitions.IGetterDefinition;
 import org.apache.royale.compiler.definitions.IInterfaceDefinition;
 import org.apache.royale.compiler.definitions.INamespaceDefinition;
 import org.apache.royale.compiler.definitions.IPackageDefinition;
+import org.apache.royale.compiler.definitions.IScopedDefinition;
 import org.apache.royale.compiler.definitions.ISetterDefinition;
+import org.apache.royale.compiler.definitions.references.INamespaceReference;
+import org.apache.royale.compiler.internal.as.codegen.BindableHelper;
+import org.apache.royale.compiler.internal.scopes.ASScope;
 import org.apache.royale.compiler.problems.DuplicateFunctionDefinitionProblem;
 import org.apache.royale.compiler.problems.UnresolvedNamespaceProblem;
 import org.apache.royale.compiler.projects.ICompilerProject;
 import org.apache.royale.compiler.scopes.IDefinitionSet;
 import org.apache.royale.compiler.tree.as.IVariableNode;
-import org.apache.royale.compiler.definitions.IScopedDefinition;
-import org.apache.royale.compiler.definitions.references.INamespaceReference;
-import org.apache.royale.compiler.internal.as.codegen.BindableHelper;
-import org.apache.royale.compiler.internal.scopes.ASScope;
 
 /**
  * {@code AccessorDefinition} is the abstract base class for definitions that
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 562b4d606..f9e41b460 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
@@ -35,8 +35,10 @@ import 
org.apache.royale.compiler.definitions.references.INamespaceReference;
 import org.apache.royale.compiler.definitions.metadata.IMetaTag;
 import org.apache.royale.compiler.definitions.metadata.IMetaTagAttribute;
 import org.apache.royale.compiler.definitions.references.IReference;
+import org.apache.royale.compiler.definitions.references.ReferenceFactory;
 import org.apache.royale.compiler.internal.definitions.metadata.MetaTag;
 import org.apache.royale.compiler.internal.projects.CompilerProject;
+import org.apache.royale.compiler.internal.semantics.SemanticUtils;
 import org.apache.royale.compiler.problems.ConflictingDefinitionProblem;
 import org.apache.royale.compiler.projects.ICompilerProject;
 import org.apache.royale.compiler.scopes.IASScope;
@@ -194,6 +196,21 @@ public class FunctionDefinition extends 
ScopedDefinitionBase implements IFunctio
                 return null;
         }
 
+        if (project.getInferTypes() && getReturnTypeReference() == null)
+        {
+            IFunctionNode funcNode = (IFunctionNode) getNode();
+            if (funcNode != null)
+            {
+                ITypeDefinition inferredReturnType = 
SemanticUtils.resolveFunctionInferredReturnType(funcNode, project);
+                if (inferredReturnType != null)
+                {
+                    
setReturnTypeReference(ReferenceFactory.resolvedReference(inferredReturnType));
+                    DependencyType dt = DependencyType.SIGNATURE;
+                    return resolveType(returnTypeReference, project, dt);
+                }
+            }
+        }
+
         // TODO We don't really need to make this a signature dependency
         // if this function is a function closure.  If this function
         // is a closure then we could make this an expression dependency
diff --git 
a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/GetterDefinition.java
 
b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/GetterDefinition.java
index 7139e3da0..b9bb2dafc 100644
--- 
a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/GetterDefinition.java
+++ 
b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/GetterDefinition.java
@@ -22,9 +22,13 @@ package org.apache.royale.compiler.internal.definitions;
 import org.apache.royale.compiler.constants.IASKeywordConstants;
 import org.apache.royale.compiler.definitions.IGetterDefinition;
 import org.apache.royale.compiler.definitions.ISetterDefinition;
+import org.apache.royale.compiler.definitions.ITypeDefinition;
 import org.apache.royale.compiler.definitions.metadata.IMetaTag;
+import org.apache.royale.compiler.definitions.references.ReferenceFactory;
+import org.apache.royale.compiler.internal.semantics.SemanticUtils;
 import org.apache.royale.compiler.problems.IncompatibleOverrideProblem;
 import org.apache.royale.compiler.projects.ICompilerProject;
+import org.apache.royale.compiler.tree.as.IGetterNode;
 
 public class GetterDefinition extends AccessorDefinition implements 
IGetterDefinition
 {
@@ -116,4 +120,26 @@ public class GetterDefinition extends AccessorDefinition 
implements IGetterDefin
 
         return override;
     }
+
+    @Override
+    public TypeDefinitionBase resolveType(ICompilerProject project)
+    {
+        if (project.getInferTypes() && getTypeReference() == null)
+        {
+            IGetterNode getterNode = (IGetterNode) getNode();
+            ITypeDefinition typeDef = 
SemanticUtils.resolveFunctionInferredReturnType(getterNode, project);
+            if (typeDef != null)
+            {
+                setTypeReference(ReferenceFactory.resolvedReference(typeDef));
+                return (TypeDefinitionBase) typeDef;
+            }
+        }
+        return super.resolveType(project);
+    }
+
+    @Override
+    public ITypeDefinition resolveReturnType(ICompilerProject project)
+    {
+        return resolveType(project);
+    }
 }
diff --git 
a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/ParameterDefinition.java
 
b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/ParameterDefinition.java
index 25cd2f979..e76b90691 100644
--- 
a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/ParameterDefinition.java
+++ 
b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/ParameterDefinition.java
@@ -22,9 +22,11 @@ package org.apache.royale.compiler.internal.definitions;
 import org.apache.royale.compiler.common.DependencyType;
 import org.apache.royale.compiler.constants.IASLanguageConstants.BuiltinType;
 import org.apache.royale.compiler.definitions.IParameterDefinition;
+import org.apache.royale.compiler.definitions.ITypeDefinition;
 import org.apache.royale.compiler.definitions.references.IReference;
 import org.apache.royale.compiler.definitions.references.ReferenceFactory;
 import org.apache.royale.compiler.internal.scopes.CatchScope;
+import org.apache.royale.compiler.internal.semantics.SemanticUtils;
 import org.apache.royale.compiler.projects.ICompilerProject;
 import org.apache.royale.compiler.scopes.IASScope;
 import org.apache.royale.compiler.tree.as.IParameterNode;
@@ -75,6 +77,25 @@ public class ParameterDefinition extends VariableDefinition 
implements IParamete
         flags |= FLAG_DEFAULT;
     }
 
+    @Override
+    public TypeDefinitionBase resolveType(ICompilerProject project)
+    {
+        if (project.getInferTypes() && getTypeReference() == null)
+        {
+            IParameterNode paramNode = (IParameterNode) getNode();
+            if (paramNode != null)
+            {
+                ITypeDefinition typeDef = 
SemanticUtils.resolveVariableInferredType(paramNode, project);
+                if (typeDef != null)
+                {
+                    
setTypeReference(ReferenceFactory.resolvedReference(typeDef));
+                    return (TypeDefinitionBase) typeDef;
+                }
+            }
+        }
+        return super.resolveType(project);
+    }
+
     @Override
     public Object resolveDefaultValue(ICompilerProject project)
     {
diff --git 
a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/SetterDefinition.java
 
b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/SetterDefinition.java
index 8d877afd3..01d4ef66b 100644
--- 
a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/SetterDefinition.java
+++ 
b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/SetterDefinition.java
@@ -22,9 +22,13 @@ package org.apache.royale.compiler.internal.definitions;
 import org.apache.royale.compiler.constants.IASKeywordConstants;
 import org.apache.royale.compiler.definitions.IGetterDefinition;
 import org.apache.royale.compiler.definitions.ISetterDefinition;
+import org.apache.royale.compiler.definitions.ITypeDefinition;
 import org.apache.royale.compiler.definitions.metadata.IMetaTag;
+import org.apache.royale.compiler.definitions.references.ReferenceFactory;
+import org.apache.royale.compiler.internal.semantics.SemanticUtils;
 import org.apache.royale.compiler.problems.IncompatibleOverrideProblem;
 import org.apache.royale.compiler.projects.ICompilerProject;
+import org.apache.royale.compiler.tree.as.ISetterNode;
 
 public class SetterDefinition extends AccessorDefinition implements 
ISetterDefinition
 {
@@ -115,4 +119,23 @@ public class SetterDefinition extends AccessorDefinition 
implements ISetterDefin
         return override;
     }
 
+    @Override
+    public TypeDefinitionBase resolveType(ICompilerProject project)
+    {
+        if (project.getInferTypes() && getTypeReference() == null)
+        {
+            ISetterNode setterNode = (ISetterNode) getNode();
+            if (setterNode != null)
+            {
+                ITypeDefinition typeDef = 
SemanticUtils.resolveVariableInferredType(setterNode, project);
+                if (typeDef != null)
+                {
+                    
setTypeReference(ReferenceFactory.resolvedReference(typeDef));
+                    return (TypeDefinitionBase) typeDef;
+                }
+            }
+        }
+        return super.resolveType(project);
+    }
+
 }
diff --git 
a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/VariableDefinition.java
 
b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/VariableDefinition.java
index 2f8a1e90d..30ca50173 100644
--- 
a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/VariableDefinition.java
+++ 
b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/VariableDefinition.java
@@ -25,8 +25,10 @@ import 
org.apache.royale.compiler.constants.IASKeywordConstants;
 import org.apache.royale.compiler.definitions.IClassDefinition;
 import org.apache.royale.compiler.definitions.IDefinition;
 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.definitions.metadata.IMetaTag;
+import org.apache.royale.compiler.definitions.references.ReferenceFactory;
 import org.apache.royale.compiler.internal.as.codegen.CodeGeneratorManager;
 import org.apache.royale.compiler.internal.as.codegen.ICodeGenerator;
 import 
org.apache.royale.compiler.internal.as.codegen.ICodeGenerator.IConstantValue;
@@ -226,6 +228,25 @@ public class VariableDefinition extends DefinitionBase 
implements IVariableDefin
         }
     }
 
+    @Override
+    public TypeDefinitionBase resolveType(ICompilerProject project)
+    {
+        if (project.getInferTypes() && getTypeReference() == null)
+        {
+            IVariableNode varNode = (IVariableNode) getNode();
+            if (varNode != null)
+            {
+                ITypeDefinition typeDef = 
SemanticUtils.resolveVariableInferredType(varNode, project);
+                if (typeDef != null)
+                {
+                    
setTypeReference(ReferenceFactory.resolvedReference(typeDef));
+                    return (TypeDefinitionBase) typeDef;
+                }
+            }
+        }
+        return super.resolveType(project);
+    }
+
     public IExpressionNode getInitializer() {
        return initializer;
        }
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 ada8f9466..6f8c7a21c 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
@@ -182,6 +182,12 @@ public class ConfigProcessor
             // TODO Auto-generated method stub
             return false;
         }
+
+        @Override
+        public boolean getInferTypes() {
+            // 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 f37c32da8..6e408f508 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
@@ -104,4 +104,10 @@ public class ASCProject extends CompilerProject implements 
IASCProject
                // TODO Auto-generated method stub
                return false;
        }
+
+       @Override
+       public boolean getInferTypes() {
+               // 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 a97354f5e..6f29509ee 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
@@ -2528,6 +2528,21 @@ public class RoyaleProject extends ASProject implements 
IRoyaleProject, ICompile
        strictIdentifierNames = enabled;
     }
 
+    private boolean inferTypes = false;
+
+    /**
+     * Indicates if type inference is enabled.
+     */
+       @Override
+       public boolean getInferTypes()
+    {
+               return inferTypes;
+       }
+    public void setInferTypes(boolean enabled)
+    {
+       inferTypes = enabled;
+    }
+
        @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 2eca5f9fd..7e08de4eb 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
@@ -273,6 +273,8 @@ public class RoyaleProjectConfigurator extends Configurator
             
project.setAllowPrivateConstructors(configuration.getCompilerAllowPrivateConstructors());
 
             
project.setStrictIdentifierNames(configuration.getCompilerStrictIdentifierNames());
+
+            project.setInferTypes(configuration.getInferTypes());
             
             project.setSwfDebugfileAlias(configuration.getSwfDebugfileAlias());
             if (configuration.getSwfDebugfileAlias() != null)
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 f76d19b17..c8adb1221 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
@@ -2623,6 +2623,14 @@ public class MethodBodySemanticChecker
         /////////////////////////////////////
         // Check for a type on the variable declaration
         String type = var.getTypeName();
+        if (project.getInferTypes() && type.isEmpty() && 
!var.hasExplicitType())
+        {
+            ITypeDefinition inferredType = 
SemanticUtils.resolveVariableInferredType(var, project);
+            if (inferredType != null)
+            {
+                type = inferredType.getQualifiedName();
+            }
+        }
        
         if (type.isEmpty())     // empty string means no declaration at all 
(not *)
         {
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 120b934c8..bf013d4a1 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
@@ -22,6 +22,7 @@ package org.apache.royale.compiler.internal.semantics;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
@@ -29,12 +30,25 @@ import org.apache.royale.abc.ABCConstants;
 import org.apache.royale.abc.semantics.Name;
 import org.apache.royale.abc.semantics.Namespace;
 import org.apache.royale.abc.semantics.Nsset;
+import org.apache.royale.compiler.common.ASModifier;
 import org.apache.royale.compiler.common.DependencyType;
 import org.apache.royale.compiler.constants.IASKeywordConstants;
 import org.apache.royale.compiler.constants.IASLanguageConstants;
 import org.apache.royale.compiler.constants.IASLanguageConstants.BuiltinType;
-import org.apache.royale.compiler.definitions.*;
+import org.apache.royale.compiler.definitions.IAccessorDefinition;
+import org.apache.royale.compiler.definitions.IClassDefinition;
+import org.apache.royale.compiler.definitions.IConstantDefinition;
+import org.apache.royale.compiler.definitions.IDefinition;
+import org.apache.royale.compiler.definitions.IFunctionDefinition;
+import org.apache.royale.compiler.definitions.IGetterDefinition;
 import 
org.apache.royale.compiler.definitions.IFunctionDefinition.FunctionClassification;
+import org.apache.royale.compiler.definitions.IInterfaceDefinition;
+import org.apache.royale.compiler.definitions.INamespaceDefinition;
+import org.apache.royale.compiler.definitions.IParameterDefinition;
+import org.apache.royale.compiler.definitions.IScopedDefinition;
+import org.apache.royale.compiler.definitions.ISetterDefinition;
+import org.apache.royale.compiler.definitions.ITypeDefinition;
+import org.apache.royale.compiler.definitions.IVariableDefinition;
 import org.apache.royale.compiler.definitions.metadata.IDeprecationInfo;
 import org.apache.royale.compiler.definitions.references.INamespaceReference;
 import org.apache.royale.compiler.definitions.references.IReference;
@@ -103,8 +117,35 @@ import 
org.apache.royale.compiler.projects.ICompilerProject;
 import org.apache.royale.compiler.scopes.IASScope;
 import org.apache.royale.compiler.scopes.IDefinitionSet;
 import org.apache.royale.compiler.tree.ASTNodeID;
-import org.apache.royale.compiler.tree.as.*;
+import org.apache.royale.compiler.tree.as.IASNode;
+import org.apache.royale.compiler.tree.as.IBinaryOperatorNode;
+import org.apache.royale.compiler.tree.as.IClassNode;
+import org.apache.royale.compiler.tree.as.ICommonClassNode;
+import org.apache.royale.compiler.tree.as.IContainerNode;
+import org.apache.royale.compiler.tree.as.IDefinitionNode;
+import org.apache.royale.compiler.tree.as.IDynamicAccessNode;
+import org.apache.royale.compiler.tree.as.IExpressionNode;
+import org.apache.royale.compiler.tree.as.IFileNode;
+import org.apache.royale.compiler.tree.as.IFunctionCallNode;
+import org.apache.royale.compiler.tree.as.IFunctionNode;
+import org.apache.royale.compiler.tree.as.IGetterNode;
+import org.apache.royale.compiler.tree.as.IIdentifierNode;
+import org.apache.royale.compiler.tree.as.IImportNode;
+import org.apache.royale.compiler.tree.as.IInterfaceNode;
+import org.apache.royale.compiler.tree.as.ILanguageIdentifierNode;
 import 
org.apache.royale.compiler.tree.as.ILanguageIdentifierNode.LanguageIdentifierKind;
+import org.apache.royale.compiler.tree.as.ILiteralNode;
+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.IReturnNode;
+import org.apache.royale.compiler.tree.as.IScopedNode;
+import org.apache.royale.compiler.tree.as.ISetterNode;
+import org.apache.royale.compiler.tree.as.ITryNode;
+import org.apache.royale.compiler.tree.as.ITypeNode;
+import org.apache.royale.compiler.tree.as.IUnaryOperatorNode;
+import org.apache.royale.compiler.tree.as.IVariableNode;
 import org.apache.royale.compiler.tree.mxml.IMXMLEventSpecifierNode;
 
 /**
@@ -2731,7 +2772,15 @@ public class SemanticUtils
                 ILanguageIdentifierNode identifier = (ILanguageIdentifierNode) 
paramType;
                 if 
(identifier.getKind().equals(LanguageIdentifierKind.ANY_TYPE))
                 {
-                    scope.addProblem(new 
ParameterHasNoTypeDeclarationProblem(paramNode, paramNode.getName(), 
node.getName()));
+                    ITypeDefinition inferredTypeDefinition = null;
+                    if (scope.getProject().getInferTypes())
+                    {
+                        inferredTypeDefinition = 
SemanticUtils.resolveVariableInferredType(paramNode, scope.getProject());
+                    }
+                    if (inferredTypeDefinition == null)
+                    {
+                        scope.addProblem(new 
ParameterHasNoTypeDeclarationProblem(paramNode, paramNode.getName(), 
node.getName()));
+                    }
                 }
             }
         }
@@ -2757,9 +2806,14 @@ public class SemanticUtils
             return;
         
         IExpressionNode returnType = node.getReturnTypeNode();
+        ITypeDefinition inferredReturnTypeDef = null;
+        if (scope.getProject().getInferTypes() && returnType == null && func 
!= null)
+        {
+            inferredReturnTypeDef = 
SemanticUtils.resolveFunctionInferredReturnType(node, scope.getProject());
+        }
         
         // check for return type declaration
-        if (returnType == null)       
+        if (returnType == null && inferredReturnTypeDef == null)       
         {
             // if none found, derive best source location for problem report
             IASNode sourceLoc = node;
@@ -3251,4 +3305,362 @@ public class SemanticUtils
         }
         return file_name;
     }
+
+    public static ITypeDefinition resolveVariableInferredType(IVariableNode 
iNode, ICompilerProject project)
+    {
+        if (iNode instanceof IGetterNode)
+        {
+            IGetterNode getterNode = (IGetterNode) iNode;
+            return resolveFunctionInferredReturnType(getterNode, project);
+        }       
+        ISetterDefinition setterDef = null;
+        if (iNode instanceof ISetterNode)
+        {
+            ISetterNode setterNode = (ISetterNode) iNode;
+            setterDef = (ISetterDefinition) setterNode.getDefinition();
+        }       
+        else if (iNode instanceof IParameterNode)
+        {
+            // if we have a parameter, check if it belongs to a setter function
+            // we can use the setter to resolve the type
+            IParameterNode paramNode = (IParameterNode) iNode;
+            IASNode parentNode = paramNode.getParent();
+            if (parentNode != null)
+            {
+                IASNode gpNode = parentNode.getParent();
+                if (gpNode instanceof ISetterNode)
+                {
+                    ISetterNode setterNode = (ISetterNode) gpNode;
+                    setterDef = (ISetterDefinition) setterNode.getDefinition();
+                }
+            }
+        }
+        if (setterDef != null)
+        {
+            // setters won't have an assigned value to infer from, but we
+            // could either infer from the super setter (if the setter is an
+            // override), or from a corresponding getter
+            ISetterDefinition overriddenSetterDef = (ISetterDefinition) 
setterDef.resolveOverriddenFunction(project);
+            if (overriddenSetterDef != null)
+            {
+                ITypeDefinition resolvedType = 
overriddenSetterDef.resolveType(project);
+                if (resolvedType != null && 
getBuiltinType(BuiltinType.ANY_TYPE, project).equals(resolvedType))
+                {
+                    // see note below about the * type
+                    return null;
+                }
+                return resolvedType;
+            }
+            else
+            {
+                IGetterDefinition getterDef = setterDef.resolveGetter(project);
+                if (getterDef != null)
+                {
+                    ITypeDefinition resolvedType = 
getterDef.resolveReturnType(project);
+                    if (resolvedType != null && 
getBuiltinType(BuiltinType.ANY_TYPE, project).equals(resolvedType))
+                    {
+                        // see note below about the * type
+                        return null;
+                    }
+                    return resolvedType;
+                }
+            }
+        }
+        IExpressionNode assignedValueNode = iNode.getAssignedValueNode();
+        if (assignedValueNode == null)
+        {
+            // nothing to infer a type from
+            return null;
+        }
+        if (ASTNodeID.LiteralNullID.equals(assignedValueNode.getNodeID()))
+        {
+            // we can't infer a specific type from null
+            return null;
+        }
+        ITypeDefinition resolvedType = assignedValueNode.resolveType(project);
+        if (getBuiltinType(BuiltinType.ANY_TYPE, project).equals(resolvedType))
+        {
+            // users should still get a missing type warning for the * type.
+            // if they want to get rid of the warning, they should explicitly
+            // declare the * type.
+            // keeping the missing type warning for * encourages the use of 
more
+            // specific types, and ensures that * is used only when needed.
+            return null;
+        }
+        return resolvedType;
+    }
+
+    public static ITypeDefinition 
resolveFunctionInferredReturnType(IFunctionNode iNode, ICompilerProject project)
+    {
+        if (iNode.hasModifier(ASModifier.OVERRIDE))
+        {
+            // if this is an override, resolve the return type from the 
original
+            IFunctionDefinition funcDef = (IFunctionDefinition) 
iNode.getDefinition();
+            if (funcDef != null)
+            {
+                IFunctionDefinition overridenFuncDef = 
funcDef.resolveOverriddenFunction(project);
+                if (overridenFuncDef != null)
+                {
+                    return overridenFuncDef.resolveReturnType(project);
+                }
+            }
+        }
+        if (iNode instanceof IGetterNode)
+        {
+            // first, try to find an explicit parameter type from the setter
+            IGetterNode getterNode = (IGetterNode) iNode;
+            IGetterDefinition getterDef = (IGetterDefinition) 
getterNode.getDefinition();
+            if (getterDef != null)
+            {
+                ISetterDefinition setterDef = getterDef.resolveSetter(project);
+                if (setterDef != null)
+                {
+                    ISetterNode setterNode = (ISetterNode) setterDef.getNode();
+                    if (setterNode != null)
+                    {
+                        IParameterNode[] paramNodes = 
setterNode.getParameterNodes();
+                        if (paramNodes != null && paramNodes.length > 0)
+                        {
+                            IParameterNode firstSetterParamNode = 
paramNodes[0];
+                            IExpressionNode varTypeNode = 
firstSetterParamNode.getVariableTypeNode();
+                            if (varTypeNode != null)
+                            {
+                                boolean isImplicitAny = 
varTypeNode.getAbsoluteStart() == -1
+                                    && varTypeNode.getAbsoluteEnd() == -1
+                                    && varTypeNode instanceof 
ILanguageIdentifierNode
+                                    && ((ILanguageIdentifierNode) 
varTypeNode).getKind().equals(LanguageIdentifierKind.ANY_TYPE);
+                                if (!isImplicitAny)
+                                {
+                                    IDefinition typeDef = 
varTypeNode.resolve(project);
+                                    if (typeDef instanceof ITypeDefinition)
+                                    {
+                                        return (ITypeDefinition) typeDef;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if (iNode instanceof ISetterNode)
+        {
+            return 
project.getBuiltinType(IASLanguageConstants.BuiltinType.VOID);
+        }
+        if (iNode.hasModifier(ASModifier.ABSTRACT))
+        {
+            // we can't infer the return type of an abstract method because it
+            // won't have a body
+            return null;
+        }
+        ITypeNode parentInterfaceNode = (IInterfaceNode) 
iNode.getAncestorOfType(IInterfaceNode.class);
+        if (parentInterfaceNode != null)
+        {
+            // we can't infer the return type of a method on an interface
+            // because it won't have a body
+            return null;
+        }
+        List<IReturnNode> returnNodes = new ArrayList<IReturnNode>();
+        findReturnNodes(iNode, returnNodes);
+        ITypeDefinition foundTypeDef = null;
+        boolean hasReturnValueNode = false;
+        for(IReturnNode returnNode : returnNodes)
+        {
+            IExpressionNode returnValueNode = returnNode.getReturnValueNode();
+            // nothing to infer a type from
+            if (returnValueNode == null || 
ASTNodeID.NilID.equals(returnValueNode.getNodeID()))
+            {
+                continue;
+            }
+            // we can't infer a specific type from null
+            if (ASTNodeID.LiteralNullID.equals(returnValueNode.getNodeID()))
+            {
+                hasReturnValueNode = true;
+                continue;
+            }
+            ITypeDefinition typeDef = returnNode.resolveType(project);
+            if (!hasReturnValueNode && foundTypeDef == null)
+            {
+                foundTypeDef = typeDef;
+            }
+            else
+            {
+                foundTypeDef = SemanticUtils.resolveCommonType(foundTypeDef, 
typeDef, project);
+            }
+            hasReturnValueNode = true;
+        }
+        if (foundTypeDef != null && !getBuiltinType(BuiltinType.ANY_TYPE, 
project).equals(foundTypeDef))
+        {
+            // users should still get a missing type warning for the * type.
+            // if they want to get rid of the warning, they should explicitly
+            // declare the * type.
+            // keeping the missing type warning for * encourages the use of 
more
+            // specific types, and ensures that * is used only when needed.
+            return foundTypeDef;
+        }
+        if (!hasReturnValueNode && !(iNode instanceof IGetterNode))
+        {
+            // there were either no return statements, or only ones without a 
value
+            return 
project.getBuiltinType(IASLanguageConstants.BuiltinType.VOID);
+        }
+        return null;
+    }
+
+    private static void findReturnNodes(IASNode node, List<IReturnNode> result)
+    {
+        for(int i = 0; i < node.getChildCount(); i++)
+        {
+            IASNode child = node.getChild(i);
+            if (child instanceof IReturnNode)
+            {
+                result.add((IReturnNode)child);
+                continue;
+            }
+            if(child.isTerminal())
+            {
+                continue;
+            }
+            findReturnNodes(child, result);
+        }
+    }
+
+    /**
+     * Resolves a common interface. Checks if A == B, if A extends B, or
+     * if B extends A. Does not check if both A and B extend a common interface
+     * C because A and B could have multiple common interfaces, and there is no
+     * clear way to choose one of those common interfaces over another.
+     */
+    public static IInterfaceDefinition resolveCommonType(IInterfaceDefinition 
interfaceA, IInterfaceDefinition interfaceB, ICompilerProject project)
+    {
+        if (interfaceA == null || interfaceB == null)
+        {
+            return null;
+        }
+        if (interfaceA.equals(interfaceB))
+        {
+            return interfaceA;
+        }
+        Iterator<IInterfaceDefinition> interfacesA = 
interfaceA.interfaceIterator(project, true);
+        while (interfacesA.hasNext())
+        {
+            IInterfaceDefinition a = interfacesA.next();
+            if (interfaceB.equals(a))
+            {
+                return interfaceB;
+            }
+        }
+        Iterator<IInterfaceDefinition> interfacesB = 
interfaceB.interfaceIterator(project, true);
+        while (interfacesB.hasNext())
+        {
+            IInterfaceDefinition b = interfacesB.next();
+            if (interfaceA.equals(b))
+            {
+                return interfaceA;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Checks if A implements B. Does not check if both A and B implement a
+     * common interface C because A and B could have multiple common 
interfaces,
+     * and there is no clear way to choose one of those common interfaces over
+     * another.
+     */
+    public static IInterfaceDefinition 
resolveCommonBaseInterface(IClassDefinition classA, IInterfaceDefinition 
interfaceB, ICompilerProject project)
+    {
+        if (classA == null || interfaceB == null)
+        {
+            return null;
+        }
+        Iterator<IInterfaceDefinition> interfacesA = 
classA.interfaceIterator(project);
+        while (interfacesA.hasNext())
+        {
+            IInterfaceDefinition a = interfacesA.next();
+            if (interfaceB.equals(a))
+            {
+                return interfaceB;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Checks if B implements A. Does not check if both A and B implement a
+     * common interface C because A and B could have multiple common 
interfaces,
+     * and there is no clear way to choose one of those common interfaces over
+     * another.
+     */
+    public static IInterfaceDefinition 
resolveCommonBaseInterface(IInterfaceDefinition interfaceA, IClassDefinition 
classB, ICompilerProject project)
+    {
+        return resolveCommonBaseInterface(classB, interfaceA, project);
+    }
+
+    /**
+     * Resolves a common class. Checks if A == B, if A extends B, or
+     * if B extends A. Does not check if both A and B implement a common
+     * interface C because A and B could implement multiple common interfaces,
+     * and there is no clear way to choose one of those common interfaces over
+     * another.
+     */
+    public static IClassDefinition resolveCommonType(IClassDefinition classA, 
IClassDefinition classB, ICompilerProject project)
+    {
+        if (classA == null || classB == null)
+        {
+            return null;
+        }
+        if (isNumericType(classA, project)
+                && isNumericType(classB, project)
+                && !classA.equals(classB)) {
+            return (IClassDefinition) getBuiltinType(BuiltinType.NUMBER, 
project);
+        }
+        Iterator<IClassDefinition> classesA = classA.classIterator(project, 
true);
+        while (classesA.hasNext())
+        {
+            IClassDefinition a = classesA.next();
+            Iterator<IClassDefinition> classesB = 
classB.classIterator(project, true);
+            while (classesB.hasNext())
+            {
+                IClassDefinition b = classesB.next();
+                if (a.equals(b))
+                {
+                    return a;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Resolves a common type. Depending on whether each type is a class or an
+     * interface, checks if A == B, if A extends B, if B extends A,
+     * if A implements B, or if B implements A. Does not check if both A and B
+     * implement a common interface C because A and B could implement multiple
+     * common interfaces, and there is no clear way to choose one of those
+     * common interfaces over another.
+     */
+    public static ITypeDefinition resolveCommonType(ITypeDefinition typeA, 
ITypeDefinition typeB, ICompilerProject project)
+    {
+        if (typeA == null || typeB == null)
+        {
+            return null;
+        }
+        if (typeA instanceof IClassDefinition && typeB instanceof 
IClassDefinition)
+        {
+            return resolveCommonType((IClassDefinition) typeA, 
(IClassDefinition) typeB, project);
+        }
+        if (typeA instanceof IInterfaceDefinition && typeB instanceof 
IInterfaceDefinition)
+        {
+            return resolveCommonType((IInterfaceDefinition) typeA, 
(IInterfaceDefinition) typeB, project);
+        }
+        if (typeA instanceof IClassDefinition && typeB instanceof 
IInterfaceDefinition)
+        {
+            return resolveCommonType((IClassDefinition) typeA, 
(IInterfaceDefinition) typeB, project);
+        }
+        if (typeA instanceof IInterfaceDefinition && typeB instanceof 
IClassDefinition)
+        {
+            return resolveCommonType((IClassDefinition) typeA, 
(IInterfaceDefinition) typeB, project);
+        }
+        return null;
+    }
 }
diff --git 
a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/ReturnNode.java
 
b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/ReturnNode.java
index 674f48b47..c808b99a0 100644
--- 
a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/ReturnNode.java
+++ 
b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/ReturnNode.java
@@ -19,6 +19,8 @@
 
 package org.apache.royale.compiler.internal.tree.as;
 
+import org.apache.royale.compiler.constants.IASLanguageConstants.BuiltinType;
+import org.apache.royale.compiler.definitions.ITypeDefinition;
 import org.apache.royale.compiler.parsing.IASToken;
 import org.apache.royale.compiler.projects.ICompilerProject;
 import org.apache.royale.compiler.tree.ASTNodeID;
@@ -62,8 +64,17 @@ public class ReturnNode extends BaseStatementExpressionNode 
implements IReturnNo
     //
     // ExpressionNodeBase overrides
     //
-    
-    // TODO Does this class need to override resolveType()?
+     
+    @Override
+    public ITypeDefinition resolveType(ICompilerProject project)
+    {
+        IExpressionNode returnValueNode = getReturnValueNode();
+        if (returnValueNode != null)
+        {
+            return returnValueNode.resolveType(project);
+        }
+        return null;
+    }
 
     @Override
     protected ReturnNode copy()
diff --git a/compiler/src/test/java/as/ASFeatureTestsBase.java 
b/compiler/src/test/java/as/ASFeatureTestsBase.java
index 3e6ff8ab1..d49084d15 100644
--- a/compiler/src/test/java/as/ASFeatureTestsBase.java
+++ b/compiler/src/test/java/as/ASFeatureTestsBase.java
@@ -188,6 +188,13 @@ public class ASFeatureTestsBase
         String results = compile(tempASFile, source, withFramework, withRPC, 
withSpark, otherOptions, false);
         assertThat(results, is(errors));
     }
+       
+    protected void compileAndExpectNoErrors(String source, boolean 
withFramework, boolean withRPC, boolean withSpark, String[] otherOptions)
+    {
+        File tempASFile = generateTempFile(source);
+        String results = compile(tempASFile, source, withFramework, withRPC, 
withSpark, otherOptions, false);
+        assertThat(results, is(""));
+    }
 
        protected void compileAndRun(String source, boolean withFramework, 
boolean withRPC, boolean withSpark, String[] otherOptions)
        {
diff --git a/compiler/src/test/java/as/ASInferTypesTests.java 
b/compiler/src/test/java/as/ASInferTypesTests.java
new file mode 100644
index 000000000..20a60c214
--- /dev/null
+++ b/compiler/src/test/java/as/ASInferTypesTests.java
@@ -0,0 +1,1912 @@
+/*
+ *
+ *  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 java.io.File;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ASInferTypesTests extends ASFeatureTestsBase
+{
+       // ----- local variables
+
+    @Test
+    public void 
testLocalVariableHasNoTypeDeclarationWarning_withInferTypesDisabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "var s = \"hello\";"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipLocalVariableHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no warning for variable because String is inferred
+            "var s = \"hello\";"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testLocalVariableHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueNull()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from null
+            "var s = null;"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testLocalVariableHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefined()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from undefined
+            "var s = undefined;"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipLocalVariableHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefinedAndDeclaredAnyType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no warning for undefined when the * type is declared
+            "var s:* = undefined;"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       // ----- parameters
+
+       @Test
+    public void 
testParameterHasNoTypeDeclarationWarning_withInferTypesDisabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "function f(s = \"hello\"):void {}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "parameter 
's' for function 'f' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipParameterHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no warning for parameter because String is inferred
+            "function f(s = \"hello\"):void {}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testParameterHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueNull()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from null
+            "function f(s = null):void {}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "parameter 
's' for function 'f' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testParameterHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefined()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from undefined
+            "function f(s = undefined):void {}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "parameter 
's' for function 'f' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipParameterHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefinedAndDeclaredAnyType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no warning for undefined when the * type is declared
+            "function f(s:* = undefined):void {}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       // ----- returns
+
+       @Test
+    public void 
testReturnValueHasNoTypeDeclarationWarning_withInferTypesDisabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "function f() { return \"hello\"; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "return 
value for function 'f' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipReturnValueHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no warning for return value because String is 
inferred
+            "function f() { return \"hello\"; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testReturnValueHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueNull()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from null
+            "function f() { return null; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "return 
value for function 'f' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testReturnValueHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefined()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from undefined
+            "function f() { return undefined; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "return 
value for function 'f' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipReturnValueHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefinedAndDeclaredAnyType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from undefined
+            "function f():* { return undefined; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testReturnValueHasNoTypeDeclarationWarning_withInferTypesDisabledAndNoReturnStatements()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "function f() {}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "return 
value for function 'f' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipReturnValueHasNoTypeDeclarationWarning_withInferTypesEnabledAndNoReturnStatements()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no return statements means that void is inferred
+            "function f() {}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testReturnValueHasNoTypeDeclarationWarning_withInferTypesDisabledAndNoReturnValues()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "function f() { return; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "return 
value for function 'f' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipReturnValueHasNoTypeDeclarationWarning_withInferTypesEnabledAndNoReturnValues()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no return statements with values means that void is 
inferred
+            "function f() { return; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testReturnValueHasNoTypeDeclarationWarning_withInferTypesDisabledAndOverrideInferredType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function f() { return \"hello\"; }",
+                       "}",
+            "class D extends C {",
+                       "override public function f() { return null; }",
+            "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "return 
value for function 'f' has no type declaration.\nreturn value for function 'f' 
has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipReturnValueHasNoTypeDeclarationWarning_withInferTypesEnabledAndOverrideInferredType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function f() { return \"hello\"; }",
+                       "}",
+            "class D extends C {",
+                       "override public function f() { return null; }",
+            "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testReturnValueHasNoTypeDeclarationWarning_withInferTypesDisabledAndOverrideDeclaredType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function f():String { return null; }",
+                       "}",
+            "class D extends C {",
+                       "override public function f() { return null; }",
+            "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        
+        compileAndExpectErrors(source, false,false,false, options, 
"Incompatible override.\nreturn value for function 'f' has no type 
declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipReturnValueHasNoTypeDeclarationWarning_withInferTypesEnabledAndOverrideDeclaredType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function f():String { return null; }",
+                       "}",
+            "class D extends C {",
+                       "override public function f() { return null; }",
+            "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       // ----- member variables
+
+       @Test
+    public void 
testMemberVariableHasNoTypeDeclarationWarning_withInferTypesDisabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C { public var s = \"hello\"; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipMemberVariableHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no warning for variable because String is inferred
+            "class C { public var s = \"hello\"; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testMemberVariableHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueNull()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from null
+            "class C { public var s = null; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testMemberVariableHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefined()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from undefined
+            "class C { public var s = undefined; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipMemberVariableHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefinedAndDeclaredAnyType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no warning for undefined when the * type is declared
+            "class C { public var s:* = undefined; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       // ----- static variables
+
+       @Test
+    public void 
testStaticVariableHasNoTypeDeclarationWarning_withInferTypesDisabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C { public static var s = \"hello\"; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipStaticVariableHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no warning for variable because String is inferred
+            "class C { public static var s = \"hello\"; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testStaticVariableHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueNull()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from null
+            "class C { public static var s = null; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testStaticVariableHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefined()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from undefined
+            "class C { public static var s = undefined; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipStaticVariableHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefinedAndDeclaredAnyType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no warning for undefined when the * type is declared
+            "class C { public static var s:* = undefined; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       // ----- static constants
+
+       @Test
+    public void 
testStaticConstantHasNoTypeDeclarationWarning_withInferTypesDisabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C { public static const s = \"hello\"; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipStaticConstantHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no warning for variable because String is inferred
+            "class C { public static const s = \"hello\"; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testStaticConstantHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueNull()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from null
+            "class C { public static const s = null; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testStaticConstantHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefined()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from undefined
+            "class C { public static const s = undefined; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipStaticConstantHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefinedAndDeclaredAnyType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no warning for undefined when the * type is declared
+            "class C { public static const s:* = undefined; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       // ----- member constants
+
+       @Test
+    public void 
testMemberConstantHasNoTypeDeclarationWarning_withInferTypesDisabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C { public const s = \"hello\"; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipMemberConstantHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no warning for variable because String is inferred
+            "class C { public const s = \"hello\"; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testMemberConstantHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueNull()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from null
+            "class C { public const s = null; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testMemberConstantHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefined()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from undefined
+            "class C { public const s = undefined; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipMemberConstantHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefinedAndDeclaredAnyType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no warning for undefined when the * type is declared
+            "class C { public const s:* = undefined; }"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       // ----- local constants
+
+       @Test
+    public void 
testLocalConstantHasNoTypeDeclarationWarning_withInferTypesDisabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "const s = \"hello\";"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipLocalConstantHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no warning for variable because String is inferred
+            "const s = \"hello\";"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testLocalConstantHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueNull()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from null
+            "const s = null;"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testLocalConstantHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefined()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // can't infer a type from undefined
+            "const s = undefined;"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "variable 
's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipLocalConstantHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefinedAndDeclaredAnyType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+                       // no warning for undefined when the * type is declared
+            "const s:* = undefined;"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       // ----- getters and setters
+
+       @Test
+    public void 
testSetterParameterHasNoTypeDeclarationWarning_withInferTypesDisabledAndGetterDeclaredString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s():String { return null; }",
+                       "public function set s(v):void {}",
+                       "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "parameter 
'v' for function 's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipSetterParameterHasNoTypeDeclarationWarning_withInferTypesEnabledAndGetterDeclaredString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s():String { return null; }",
+                       "public function set s(v):void {}",
+                       "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testGetterReturnValueHasNoTypeDeclarationWarning_withInferTypesDisabledAndSetterDeclaredString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s() { return null; }",
+                       "public function set s(v:String):void {}",
+                       "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "return 
value for function 's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipGetterReturnValueHasNoTypeDeclarationWarning_withInferTypesEnabledAndSetterDeclaredString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s() { return null; }",
+                       "public function set s(v:String):void {}",
+                       "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testGetterReturnValueHasNoTypeDeclarationWarningAndSetterParameterHasNoTypeDeclarationWarning_withInferTypesDisabledAndGetterDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s() { return \"hello\"; }",
+                       "public function set s(v):void {}",
+                       "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "return 
value for function 's' has no type declaration.\nparameter 'v' for function 's' 
has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipGetterReturnValueHasNoTypeDeclarationWarningAndSetterParameterHasNoTypeDeclarationWarning_withInferTypesEnabledAndGetterDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s() { return \"hello\"; }",
+                       "public function set s(v):void {}",
+                       "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testGetterReturnValueHasNoTypeDeclarationWarning_withInferTypesDisabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s() { return \"hello\"; }",
+                       "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "return 
value for function 's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipGetterReturnValueHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueString()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s() { return \"hello\"; }",
+                       "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testGetterReturnValueHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueNull()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s() { return null; }",
+                       "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "return 
value for function 's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testGetterReturnValueHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefined()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s() { return undefined; }",
+                       "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "return 
value for function 's' has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipGetterReturnValueHasNoTypeDeclarationWarning_withInferTypesEnabledAndDefaultValueUndefinedAndDeclaredAnyType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s():* { return undefined; }",
+                       "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testGetterReturnValueHasNoTypeDeclarationWarning_withInferTypesDisabledAndOverrideInferredType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s() { return \"hello\"; }",
+                       "}",
+            "class D extends C {",
+                       "override public function get s() { return null; }",
+            "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "return 
value for function 's' has no type declaration.\nreturn value for function 's' 
has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipGetterReturnValueHasNoTypeDeclarationWarning_withInferTypesEnabledAndOverrideInferredType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s() { return \"hello\"; }",
+                       "}",
+            "class D extends C {",
+                       "override public function get s() { return null; }",
+            "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testGetterReturnValueHasNoTypeDeclarationWarning_withInferTypesDisabledAndOverrideDeclaredType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s():String { return null; }",
+                       "}",
+            "class D extends C {",
+                       "override public function get s() { return null; }",
+            "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        
+        compileAndExpectErrors(source, false,false,false, options, 
"Incompatible override.\nreturn value for function 's' has no type 
declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipGetterReturnValueHasNoTypeDeclarationWarning_withInferTypesEnabledAndOverrideDeclaredType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s():String { return null; }",
+                       "}",
+            "class D extends C {",
+                       "override public function get s() { return null; }",
+            "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testSetterParameterHasNoTypeDeclarationWarning_withInferTypesDisabledAndOverrideDeclaredType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function set s(p:String):void {}",
+                       "}",
+            "class D extends C {",
+                       "override public function set s(p):void {}",
+            "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        
+        compileAndExpectErrors(source, false,false,false, options, 
"Incompatible override.\nparameter 'p' for function 's' has no type 
declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipSetterParameterHasNoTypeDeclarationWarning_withInferTypesEnabledAndOverrideDeclaredType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function set s(p:String):void {}",
+                       "}",
+            "class D extends C {",
+                       "override public function set s(p):void {}",
+            "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testSetterParameterHasNoTypeDeclarationWarning_withInferTypesDisabledAndOverrideInferredType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s() { return \"hello\"; }",
+                       "public function set s(p):void {}",
+                       "}",
+            "class D extends C {",
+                       "override public function set s(p):void {}",
+            "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        
+        compileAndExpectErrors(source, false,false,false, options, "return 
value for function 's' has no type declaration.\nparameter 'p' for function 's' 
has no type declaration.\nparameter 'p' for function 's' has no type 
declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipSetterParameterHasNoTypeDeclarationWarning_withInferTypesEnabledAndOverrideInferredType()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s() { return \"hello\"; }",
+                       "public function set s(p):void {}",
+                       "}",
+            "class D extends C {",
+                       "override public function set s(p):void {}",
+            "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+
+       @Test
+    public void 
testSetterParameterHasNoTypeDeclarationWarning_withInferTypesDisabledAndOverrideInferredType2()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s():String { return null; }",
+                       "public function set s(p):void {}",
+                       "}",
+            "class D extends C {",
+                       "override public function set s(p):void {}",
+            "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=false"
+        };
+        
+        compileAndExpectErrors(source, false,false,false, options, "parameter 
'p' for function 's' has no type declaration.\nparameter 'p' for function 's' 
has no type declaration.\n");
+    }
+
+       @Test
+    public void 
testSkipSetterParameterHasNoTypeDeclarationWarning_withInferTypesEnabledAndOverrideInferredType2()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            "class C {",
+                       "public function get s():String { return null; }",
+                       "public function set s(p):void {}",
+                       "}",
+            "class D extends C {",
+                       "override public function set s(p):void {}",
+            "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-infer-types=true"
+        };
+        compileAndExpectNoErrors(source, false,false,false, options);
+    }
+}


Reply via email to