You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by jo...@apache.org on 2024/04/11 16:09:36 UTC

(royale-compiler) branch develop updated: compiler: abstract getters/setters

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


The following commit(s) were added to refs/heads/develop by this push:
     new 4a9426316 compiler: abstract getters/setters
4a9426316 is described below

commit 4a942631604a3adab7feafe825d3910a4589c7e5
Author: Josh Tynjala <jo...@apache.org>
AuthorDate: Thu Mar 28 13:53:15 2024 -0700

    compiler: abstract getters/setters
---
 RELEASE_NOTES.md                                   |    1 +
 .../js/royale/TestRoyaleAccessorMembers.java       |   48 +-
 .../as/codegen/ClassDirectiveProcessor.java        |   10 +
 .../internal/definitions/ClassDefinition.java      |   10 +-
 .../semantics/MethodBodySemanticChecker.java       |   15 +
 .../compiler/internal/semantics/SemanticUtils.java |    3 +-
 .../problems/AbstractAndOverrideProblem.java       |   40 +
 .../src/test/java/as/ASAbstractClassTests.java     | 1319 +++++++++++++++++---
 8 files changed, 1257 insertions(+), 189 deletions(-)

diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 0b3311731..db78f46f5 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -4,6 +4,7 @@ Apache Royale Compiler 0.9.11
 =============================
 
 - compiler: Added new `--infer-types` compiler option that allows the compiler to automatically detect an appropriate type for both variables and function signatures that have omitted their declared types. Type inference is based on either the initializer or return values.
+- compiler: Abstract classes now support abstract getter and setter methods.
 - compiler: Improved type checking for `&&` and `||` binary operators and `?:` ternary operator.
 - compiler: Removed obsolete "AMD" and "Goog" JavaScript backends, and finished some refactoring to make codebase easier to maintain.
 - compiler: Now requires Java 11 or newer to run. Previously required Java 8 minimum.
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleAccessorMembers.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleAccessorMembers.java
index 6701e08a3..afd58c396 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleAccessorMembers.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleAccessorMembers.java
@@ -46,7 +46,7 @@ public class TestRoyaleAccessorMembers extends TestAccessorMembers
     @Test
     public void testGetAccessor_withBody()
     {
-    	IClassNode node = (IClassNode) getNode("function get foo():int{return -1;}",
+    	  IClassNode node = (IClassNode) getNode("function get foo():int{return -1;}",
     			IClassNode.class, WRAP_LEVEL_CLASS);
         asBlockWalker.visitClass(node);
         assertOut("/**\n * @constructor\n */\nRoyaleTest_A = function() {\n};\n\n\n" +
@@ -59,7 +59,7 @@ public class TestRoyaleAccessorMembers extends TestAccessorMembers
     @Test
     public void testGetAccessor_withNamespace()
     {
-    	IClassNode node = (IClassNode) getNode("public function get foo():int{return -1;}",
+    	  IClassNode node = (IClassNode) getNode("public function get foo():int{return -1;}",
         		IClassNode.class, WRAP_LEVEL_CLASS);
         asBlockWalker.visitClass(node);
         assertOut("/**\n * @constructor\n */\nRoyaleTest_A = function() {\n};\n\n\n" +
@@ -72,7 +72,7 @@ public class TestRoyaleAccessorMembers extends TestAccessorMembers
     @Test
     public void testGetAccessor_withNamespaceOverride()
     {
-    	IClassNode node = (IClassNode) getNode("public class B extends A { public override function get foo():int{return super.foo;} }; public class A {public function get foo():int {return 0;}} ",
+    	  IClassNode node = (IClassNode) getNode("public class B extends A { public override function get foo():int{return super.foo;} }; public class A {public function get foo():int {return 0;}} ",
         		IClassNode.class, WRAP_LEVEL_PACKAGE);
         asBlockWalker.visitClass(node);
         assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() {\n  B.base(this, 'constructor');\n};\ngoog.inherits(B, A);\n\n\n" +
@@ -83,7 +83,7 @@ public class TestRoyaleAccessorMembers extends TestAccessorMembers
     @Test
     public void testGetAccessor_withGeneratedSetOverride()
     {
-    	IClassNode node = (IClassNode) getNode("public class B extends A { public override function get foo():int{return super.foo;} }; public class A { public function set foo(value:int):void{} public function get foo():int {return 0;}}",
+    	  IClassNode node = (IClassNode) getNode("public class B extends A { public override function get foo():int{return super.foo;} }; public class A { public function set foo(value:int):void{} public function get foo():int {return 0;}}",
         		IClassNode.class, WRAP_LEVEL_PACKAGE);
         asBlockWalker.visitClass(node);
         assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() {\n  B.base(this, 'constructor');\n};\ngoog.inherits(B, A);\n\n\n" +
@@ -95,7 +95,7 @@ public class TestRoyaleAccessorMembers extends TestAccessorMembers
     @Test
     public void testGetAccessor_withStatic()
     {
-    	IClassNode node = (IClassNode) getNode("public static function get foo():int{return -1;}",
+    	  IClassNode node = (IClassNode) getNode("public static function get foo():int{return -1;}",
         		IClassNode.class, WRAP_LEVEL_CLASS);
         asBlockWalker.visitClass(node);
         assertOut("/**\n * @constructor\n */\nRoyaleTest_A = function() {\n};\n\n\n" +
@@ -121,7 +121,7 @@ public class TestRoyaleAccessorMembers extends TestAccessorMembers
     @Test
     public void testGetAccessor_withNamespace_withoutReturnType()
     {
-    	IClassNode node = (IClassNode) getNode("public function get foo(){return -1;}",
+    	  IClassNode node = (IClassNode) getNode("public function get foo(){return -1;}",
         		IClassNode.class, WRAP_LEVEL_CLASS);
         asBlockWalker.visitClass(node);
         assertOut("/**\n * @constructor\n */\nRoyaleTest_A = function() {\n};\n\n\n" +
@@ -134,7 +134,7 @@ public class TestRoyaleAccessorMembers extends TestAccessorMembers
     @Test
     public void testSetAccessor()
     {
-    	IClassNode node = (IClassNode) getNode("function set foo(value:int):void{}",
+    	  IClassNode node = (IClassNode) getNode("function set foo(value:int):void{}",
         		IClassNode.class, WRAP_LEVEL_CLASS);
         asBlockWalker.visitClass(node);
         assertOut("/**\n * @constructor\n */\nRoyaleTest_A = function() {\n};\n\n\n" +
@@ -146,7 +146,7 @@ public class TestRoyaleAccessorMembers extends TestAccessorMembers
     @Test
     public void testSetAccessor_withBody()
     {
-    	IClassNode node = (IClassNode) getNode("function set foo(value:int):void{fetch('haai');}",
+    	  IClassNode node = (IClassNode) getNode("function set foo(value:int):void{fetch('haai');}",
         		IClassNode.class, WRAP_LEVEL_CLASS);
         asBlockWalker.visitClass(node);
         assertOut("/**\n * @constructor\n */\nRoyaleTest_A = function() {\n};\n\n\n" +
@@ -159,7 +159,7 @@ public class TestRoyaleAccessorMembers extends TestAccessorMembers
     @Test
     public void testSetAccessor_withNamespace()
     {
-    	IClassNode node = (IClassNode) getNode("public function set foo(value:int):void{}",
+    	  IClassNode node = (IClassNode) getNode("public function set foo(value:int):void{}",
         		IClassNode.class, WRAP_LEVEL_CLASS);
         asBlockWalker.visitClass(node);
         assertOut("/**\n * @constructor\n */\nRoyaleTest_A = function() {\n};\n\n\n" +
@@ -172,7 +172,7 @@ public class TestRoyaleAccessorMembers extends TestAccessorMembers
     @Test
     public void testSetAccessor_withNamespaceOverride()
     {
-    	IClassNode node = (IClassNode) getNode("public class B extends A { public override function set foo(value:int):void {super.foo = value;} }; public class A { public function set foo(value:int):void{}}",
+    	  IClassNode node = (IClassNode) getNode("public class B extends A { public override function set foo(value:int):void {super.foo = value;} }; public class A { public function set foo(value:int):void{}}",
         		IClassNode.class, WRAP_LEVEL_PACKAGE);
         asBlockWalker.visitClass(node);
         assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() {\n  B.base(this, 'constructor');\n};\ngoog.inherits(B, A);\n\n\n" +
@@ -184,7 +184,7 @@ public class TestRoyaleAccessorMembers extends TestAccessorMembers
     @Test
     public void testSetAccessor_withStatic()
     {
-    	IClassNode node = (IClassNode) getNode("public static function set foo(value:int):void{}",
+    	  IClassNode node = (IClassNode) getNode("public static function set foo(value:int):void{}",
         		IClassNode.class, WRAP_LEVEL_CLASS);
         asBlockWalker.visitClass(node);
         assertOut("/**\n * @constructor\n */\nRoyaleTest_A = function() {\n};\n\n\n" +
@@ -196,7 +196,7 @@ public class TestRoyaleAccessorMembers extends TestAccessorMembers
     @Test
     public void testSetAccessor_withGeneratedGetOverride()
     {
-    	IClassNode node = (IClassNode) getNode("public class B extends A { public override function set foo(value:int):void {super.foo = value;} }; public class A { public function set foo(value:int):void{} public function get foo():int { return 0;}}",
+    	  IClassNode node = (IClassNode) getNode("public class B extends A { public override function set foo(value:int):void {super.foo = value;} }; public class A { public function set foo(value:int):void{} public function get foo():int { return 0;}}",
         		IClassNode.class, WRAP_LEVEL_PACKAGE);
         asBlockWalker.visitClass(node);
         assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() {\n  B.base(this, 'constructor');\n};\ngoog.inherits(B, A);\n\n\n" +
@@ -207,7 +207,7 @@ public class TestRoyaleAccessorMembers extends TestAccessorMembers
     @Test
     public void testSetAccessorWithSuperSet()
     {
-    	IClassNode node = (IClassNode) getNode("public class B extends A { public override function set foo(value:int):void {super.foo = value;} }; public class A { public function set foo(value:int):void{} public function get foo():int { return 0;}}",
+    	  IClassNode node = (IClassNode) getNode("public class B extends A { public override function set foo(value:int):void {super.foo = value;} }; public class A { public function set foo(value:int):void{} public function get foo():int { return 0;}}",
         		IClassNode.class, WRAP_LEVEL_PACKAGE);
         asBlockWalker.visitClass(node);
         assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() {\n  B.base(this, 'constructor');\n};\ngoog.inherits(B, A);\n\n\n" +
@@ -218,7 +218,7 @@ public class TestRoyaleAccessorMembers extends TestAccessorMembers
     @Test
     public void testSetAccessorWithSuperSetAndPropagatedValue()
     {
-    	IClassNode node = (IClassNode) getNode("public class B extends A { public override function set foo(value:int):void {var z:int = super.foo = value;} }; public class A { public function set foo(value:int):void{} public function get foo():int { return 0;}}",
+    	  IClassNode node = (IClassNode) getNode("public class B extends A { public override function set foo(value:int):void {var z:int = super.foo = value;} }; public class A { public function set foo(value:int):void{} public function get foo():int { return 0;}}",
         		IClassNode.class, WRAP_LEVEL_PACKAGE);
         asBlockWalker.visitClass(node);
         assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() {\n  B.base(this, 'constructor');\n};\ngoog.inherits(B, A);\n\n\n" +
@@ -230,7 +230,7 @@ public class TestRoyaleAccessorMembers extends TestAccessorMembers
     @Test
     public void testSetAccessor_withoutParameterType()
     {
-    	IClassNode node = (IClassNode) getNode("function set foo(value):void{}",
+    	  IClassNode node = (IClassNode) getNode("function set foo(value):void{}",
         		IClassNode.class, WRAP_LEVEL_CLASS);
         asBlockWalker.visitClass(node);
         assertOut("/**\n * @constructor\n */\nRoyaleTest_A = function() {\n};\n\n\n" +
@@ -238,6 +238,24 @@ public class TestRoyaleAccessorMembers extends TestAccessorMembers
 				"RoyaleTest_A.prototype.set__foo = function(value) {\n};\n\n\n" +
         		"Object.defineProperties(RoyaleTest_A.prototype, /** @lends {RoyaleTest_A.prototype} */ {\n/**\n * @type {*}\n */\nfoo: {\nset: RoyaleTest_A.prototype.set__foo}}\n);");
     }
+
+    @Test
+    public void testGetAccessorWithAbstract()
+    {
+    	  IClassNode node = (IClassNode) getNode("public abstract class A { public abstract function get foo():int; }",
+        		IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n};\n\n\n/**\n * @nocollapse\n * @export\n * @type {number}\n */\nA.prototype.foo;\n\n\nA.prototype.get__foo = function() {\n};\n\n\nObject.defineProperties(A.prototype, /** @lends {A.prototype} */ {\n/**\n * @type {number}\n */\nfoo: {\nget: A.prototype.get__foo}}\n);");
+    }
+
+    @Test
+    public void testSetAccessorWithAbstract()
+    {
+    	  IClassNode node = (IClassNode) getNode("public abstract class A { public abstract function set foo(value:int):void; }",
+        		IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n};\n\n\n/**\n * @nocollapse\n * @export\n * @type {number}\n */\nA.prototype.foo;\n\n\nA.prototype.set__foo = function(value) {\n};\n\n\nObject.defineProperties(A.prototype, /** @lends {A.prototype} */ {\n/**\n * @type {number}\n */\nfoo: {\nset: A.prototype.set__foo}}\n);");
+    }
     
     @Override
     protected IBackend createBackend()
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/ClassDirectiveProcessor.java b/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/ClassDirectiveProcessor.java
index 281a97393..3512f0734 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/ClassDirectiveProcessor.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/ClassDirectiveProcessor.java
@@ -1216,6 +1216,16 @@ class ClassDirectiveProcessor extends DirectiveProcessor
                 {
                     classScope.addProblem(new AbstractOutsideClassProblem(site) );
                 }
+                else
+                {
+                    if (modifiersSet != null)
+                    {
+                        if( modifiersSet.hasModifier(ASModifier.OVERRIDE) )
+                        {
+                            classScope.addProblem(new AbstractAndOverrideProblem(site) );
+                        }
+                    }
+                }
             }
             else
             {
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/ClassDefinition.java b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/ClassDefinition.java
index 1b07a5592..a103ee132 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/ClassDefinition.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/ClassDefinition.java
@@ -1504,7 +1504,7 @@ public class ClassDefinition extends ClassDefinitionBase implements IClassDefini
             for (int i = 0, l = defSet.getSize(); i < l; ++i)
             {
                 IDefinition def = defSet.getDefinition(i);
-                if (def instanceof FunctionDefinition && !(def instanceof IAccessorDefinition))
+                if (def instanceof FunctionDefinition)
                 {
                     FunctionDefinition abstractMethod = (FunctionDefinition)def;
 
@@ -1534,8 +1534,14 @@ public class ClassDefinition extends ClassDefinitionBase implements IClassDefini
                     if (c == null || c.isAbstract())
                     {
                         // Error, didn't implement the method
+                        String methodName = abstractMethod.getBaseName();
+                        if (abstractMethod instanceof IGetterDefinition) {
+                            methodName = "get " + methodName;
+                        } else if (abstractMethod instanceof ISetterDefinition) {
+                            methodName = "set " + methodName;
+                        }
                         problems.add(new UnimplementedAbstractMethodProblem(cls,
-                                abstractMethod.getBaseName(),
+                                methodName,
                                 this.getBaseName(),
                                 cls.getBaseName()));
                     }
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 7ce307905..d0a0801e1 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
@@ -2187,6 +2187,21 @@ public class MethodBodySemanticChecker
         }
         
         // For super.f(...), check whether f is deprecated.
+        if (iNode instanceof IMemberAccessExpressionNode)
+        {
+            IMemberAccessExpressionNode mae = (IMemberAccessExpressionNode)iNode;
+            IExpressionNode rightNode = mae.getRightOperandNode();
+            IDefinition rightDef = rightNode.resolve(project);
+            if (rightDef instanceof IAccessorDefinition)
+            {
+                if (rightDef.isAbstract())
+                {
+                    addProblem(new AccessUndefinedPropertyProblem( 
+                            iNode, rightDef.getBaseName()
+                        ));
+                }
+            }
+        }
         if (iNode instanceof IFunctionCallNode)
         {
             IExpressionNode nameNode = ((IFunctionCallNode)iNode).getNameNode();
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 678c047a9..23d3a6bfc 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
@@ -3237,8 +3237,7 @@ public class SemanticUtils
                 return parentDef.isAbstract()
                         && !funcDef.isStatic()
                         && !funcDef.isFinal()
-                        && !funcDef.isConstructor()
-                        && !(funcDef instanceof IAccessorDefinition);
+                        && !funcDef.isConstructor();
             }
             return false;
         }
diff --git a/compiler/src/main/java/org/apache/royale/compiler/problems/AbstractAndOverrideProblem.java b/compiler/src/main/java/org/apache/royale/compiler/problems/AbstractAndOverrideProblem.java
new file mode 100644
index 000000000..4e8f2e558
--- /dev/null
+++ b/compiler/src/main/java/org/apache/royale/compiler/problems/AbstractAndOverrideProblem.java
@@ -0,0 +1,40 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package org.apache.royale.compiler.problems;
+
+import org.apache.royale.compiler.tree.as.IASNode;
+
+/**
+ * Diagnostic emitted when a function is declared "abstract" and "override"
+ */
+public final class AbstractAndOverrideProblem extends CodegenProblem
+{
+    public static final String DESCRIPTION =
+        "Functions cannot be both ${ABSTRACT} and ${OVERRIDE}.";
+
+    public AbstractAndOverrideProblem(IASNode site)
+    {
+        super(site);
+    }
+    
+    // Prevent these from being localized.
+    public final String ABSTRACT = "abstract";
+    public final String OVERRIDE = "override";
+}
diff --git a/compiler/src/test/java/as/ASAbstractClassTests.java b/compiler/src/test/java/as/ASAbstractClassTests.java
index d98c12242..34fb2fbf9 100644
--- a/compiler/src/test/java/as/ASAbstractClassTests.java
+++ b/compiler/src/test/java/as/ASAbstractClassTests.java
@@ -136,8 +136,8 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\n");
 	}
 
-	@Test
-    public void testAbstractNotAllowedOnStaticMethodError_withAllowAbstractClassesDisabled()
+    @Test
+    public void testAbstractNotAllowedOnInterfaceStaticMethodError_withAllowAbstractClassesDisabled()
     {
         String[] imports = new String[]
         {
@@ -150,9 +150,9 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"class A {",
+					"interface A {",
 					//error because abstract classes have not been enabled
-					"public static abstract function a():void",
+					"static abstract function a():void",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -161,11 +161,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=false"
         };
-        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\nFunction does not have a body.\n");
+        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\nThe static attribute may be used only on definitions inside a class.\n");
 	}
 
 	@Test
-    public void testAbstractNotAllowedOnGetterError_withAllowAbstractClassesDisabled()
+    public void testAbstractNotAllowedOnStaticMethodError_withAllowAbstractClassesDisabled()
     {
         String[] imports = new String[]
         {
@@ -180,7 +180,7 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"class A {",
 					//error because abstract classes have not been enabled
-					"public abstract function get a():Object;",
+					"public static abstract function a():void",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -189,11 +189,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=false"
         };
-        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\nFunction does not have a body.\nFunction does not return a value.\n");
+        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\nFunction does not have a body.\n");
 	}
 
 	@Test
-    public void testAbstractNotAllowedOnSetterError_withAllowAbstractClassesDisabled()
+    public void testAbstractNotAllowedOnGetterError_withAllowAbstractClassesDisabled()
     {
         String[] imports = new String[]
         {
@@ -208,7 +208,7 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"class A {",
 					//error because abstract classes have not been enabled
-					"public abstract function set a(value:Object):void;",
+					"public abstract function get a():String;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -217,11 +217,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=false"
         };
-        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\nFunction does not have a body.\n");
+        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\nFunction does not have a body.\nFunction does not return a value.\n");
 	}
 
 	@Test
-    public void testAbstractNotAllowedOnVariableError_withAllowAbstractClassesDisabled()
+    public void testAbstractNotAllowedOnSetterError_withAllowAbstractClassesDisabled()
     {
         String[] imports = new String[]
         {
@@ -236,7 +236,7 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"class A {",
 					//error because abstract classes have not been enabled
-					"public abstract var a:Object;",
+					"public abstract function set a(value:String):void;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -245,11 +245,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=false"
         };
-        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\n");
+        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\nFunction does not have a body.\n");
 	}
 
 	@Test
-    public void testAbstractNotAllowedOnStaticVariableError_withAllowAbstractClassesDisabled()
+    public void testAbstractNotAllowedOnStaticGetterError_withAllowAbstractClassesDisabled()
     {
         String[] imports = new String[]
         {
@@ -264,7 +264,7 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"class A {",
 					//error because abstract classes have not been enabled
-					"public static abstract var a:Object;",
+					"public static abstract function get a():String;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -273,11 +273,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=false"
         };
-        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\n");
+        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\nFunction does not have a body.\nFunction does not return a value.\n");
 	}
 
-    @Test
-    public void testAbstractNotAllowedOnInterfaceGetterError_withAllowAbstractClassesDisabled()
+	@Test
+    public void testAbstractNotAllowedOnStaticSetterError_withAllowAbstractClassesDisabled()
     {
         String[] imports = new String[]
         {
@@ -290,9 +290,9 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"interface A {",
+					"class A {",
 					//error because abstract classes have not been enabled
-					"abstract function get a():Object;",
+					"public static abstract function set a(value:String):void;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -301,11 +301,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=false"
         };
-        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\n");
+        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\nFunction does not have a body.\n");
 	}
 
-    @Test
-    public void testAbstractNotAllowedOnInterfaceSetterError_withAllowAbstractClassesDisabled()
+	@Test
+    public void testAbstractNotAllowedOnVariableError_withAllowAbstractClassesDisabled()
     {
         String[] imports = new String[]
         {
@@ -318,9 +318,9 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"interface A {",
+					"class A {",
 					//error because abstract classes have not been enabled
-					"abstract function set a(value:Object):void;",
+					"public abstract var a:Object;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -333,7 +333,7 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
 	}
 
 	@Test
-    public void testAbstractClassNoErrors_withAllowAbstractClassesEnabled()
+    public void testAbstractNotAllowedOnStaticVariableError_withAllowAbstractClassesDisabled()
     {
         String[] imports = new String[]
         {
@@ -346,22 +346,22 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"abstract class A {",
+					"class A {",
+					//error because abstract classes have not been enabled
+					"public static abstract var a:Object;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
 
         String[] options = new String[]
         {
-					"-allow-abstract-classes=true"
+					"-allow-abstract-classes=false"
         };
-        File tempASFile = generateTempFile(source);
-        String result = compile(tempASFile, source, false,false,false, options, true);
-        Assert.assertEquals("", result);
-    }
+        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\n");
+	}
 
-	@Test
-    public void testAbstractMethodOnClassNoErrors_withAllowAbstractClassesEnabled()
+    @Test
+    public void testAbstractNotAllowedOnInterfaceGetterError_withAllowAbstractClassesDisabled()
     {
         String[] imports = new String[]
         {
@@ -374,23 +374,22 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"abstract class A {",
-					"public abstract function a():void;",
+					"interface A {",
+					//error because abstract classes have not been enabled
+					"abstract function get a():String;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
 
         String[] options = new String[]
         {
-					"-allow-abstract-classes=true"
+					"-allow-abstract-classes=false"
         };
-		File tempASFile = generateTempFile(source);
-		String result = compile(tempASFile, source, false,false,false, options, true);
-		Assert.assertEquals("", result);
+        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\n");
 	}
 
-	@Test
-    public void testAbstractMethodWithParametersAndReturnOnClassNoErrors_withAllowAbstractClassesEnabled()
+    @Test
+    public void testAbstractNotAllowedOnInterfaceSetterError_withAllowAbstractClassesDisabled()
     {
         String[] imports = new String[]
         {
@@ -403,23 +402,22 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"abstract class A {",
-					"public abstract function a(arg0:String, arg1:Number):Boolean;",
+					"interface A {",
+					//error because abstract classes have not been enabled
+					"abstract function set a(value:String):void;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
 
         String[] options = new String[]
         {
-					"-allow-abstract-classes=true"
+					"-allow-abstract-classes=false"
         };
-		File tempASFile = generateTempFile(source);
-		String result = compile(tempASFile, source, false,false,false, options, true);
-		Assert.assertEquals("", result);
+        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\n");
 	}
 
-	@Test
-    public void testAbstractMethodOnInterfaceError_withAllowAbstractClassesEnabled()
+    @Test
+    public void testAbstractNotAllowedOnInterfaceStaticGetterError_withAllowAbstractClassesDisabled()
     {
         String[] imports = new String[]
         {
@@ -433,20 +431,21 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         String[] extra = new String[]
         {
 					"interface A {",
-					"abstract function a():void;",
+					//error because abstract classes have not been enabled
+					"static abstract function get a():String;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
 
         String[] options = new String[]
         {
-					"-allow-abstract-classes=true"
+					"-allow-abstract-classes=false"
         };
-        compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\n");
+        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\nThe static attribute may be used only on definitions inside a class.\n");
 	}
 
-	@Test
-    public void testAbstractGetterOnInterfaceError_withAllowAbstractClassesEnabled()
+    @Test
+    public void testAbstractNotAllowedOnInterfaceStaticSetterError_withAllowAbstractClassesDisabled()
     {
         String[] imports = new String[]
         {
@@ -460,20 +459,21 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         String[] extra = new String[]
         {
 					"interface A {",
-					"abstract function get a():Object;",
+					//error because abstract classes have not been enabled
+					"static abstract function set a(value:String):void;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
 
         String[] options = new String[]
         {
-					"-allow-abstract-classes=true"
+					"-allow-abstract-classes=false"
         };
-        compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\n");
+        compileAndExpectErrors(source, false,false,false, options,"'abstract' is not allowed here\nThe static attribute may be used only on definitions inside a class.\n");
 	}
 
 	@Test
-    public void testAbstractSetterOnInterfaceError_withAllowAbstractClassesEnabled()
+    public void testAbstractClassNoErrors_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -486,8 +486,7 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"interface A {",
-					"abstract function set a(value:Object):void;",
+					"abstract class A {",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -496,11 +495,13 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=true"
         };
-        compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\n");
-	}
+        File tempASFile = generateTempFile(source);
+        String result = compile(tempASFile, source, false,false,false, options, true);
+        Assert.assertEquals("", result);
+    }
 
 	@Test
-    public void testAbstractProtectedMethodNoErrors_withAllowAbstractClassesEnabled()
+    public void testAbstractMethodOnClassNoErrors_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -514,7 +515,7 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         String[] extra = new String[]
         {
 					"abstract class A {",
-					"protected abstract function a():void;",
+					"public abstract function a():void;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -529,7 +530,7 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
 	}
 
 	@Test
-    public void testAbstractInternalMethodNoErrors_withAllowAbstractClassesEnabled()
+    public void testAbstractMethodWithParametersAndReturnOnClassNoErrors_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -543,7 +544,7 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         String[] extra = new String[]
         {
 					"abstract class A {",
-					"internal abstract function a():void;",
+					"public abstract function a(arg0:String, arg1:Number):Boolean;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -558,7 +559,7 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
 	}
 
 	@Test
-    public void testAbstractPrivateMethodError_withAllowAbstractClassesEnabled()
+    public void testAbstractMethodOnInterfaceError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -571,8 +572,10 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"abstract class A {",
-					"private abstract function a():void;",
+					"interface A {",
+					//error because an abstract method may only be defined on an
+					//abstract class (not an interface)
+					"abstract function a():void;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -581,11 +584,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=true"
         };
-        compileAndExpectErrors(source, false,false,false, options, "Methods that are abstract cannot be declared private.\n");
+        compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\n");
 	}
 
 	@Test
-    public void testAbstractFinalClassError_withAllowAbstractClassesEnabled()
+    public void testAbstractGetterOnInterfaceError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -598,7 +601,10 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"abstract final class A {",
+					"interface A {",
+					//error because an abstract method may only be defined on an
+					//abstract class (not an interface)
+					"abstract function get a():String;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -611,7 +617,7 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
 	}
 
 	@Test
-    public void testAbstractFinalMethodError_withAllowAbstractClassesEnabled()
+    public void testAbstractSetterOnInterfaceError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -624,8 +630,10 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"abstract class A {",
-					"public final abstract function a():void;",
+					"interface A {",
+					//error because an abstract method may only be defined on an
+					//abstract class (not an interface)
+					"abstract function set a(value:String):void;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -634,11 +642,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=true"
         };
-        compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\nFunction does not have a body.\n");
+        compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\n");
 	}
 
 	@Test
-    public void testAbstractMethodNotInAbstractClassError_withAllowAbstractClassesEnabled()
+    public void testAbstractStaticMethodOnInterfaceError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -651,10 +659,10 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"class A {",
+					"interface A {",
 					//error because an abstract method may only be defined on an
-					//abstract class
-					"public abstract function a():void;",
+					//abstract class (not an interface)
+					"static abstract function a():void;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -663,11 +671,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=true"
         };
-		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\nFunction does not have a body.\n");
+        compileAndExpectErrors(source, false,false,false, options, "The static attribute may be used only on definitions inside a class.\nThe abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\n");
 	}
 
 	@Test
-    public void testAbstractStaticMethodError_withAllowAbstractClassesEnabled()
+    public void testAbstractStaticGetterOnInterfaceError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -680,9 +688,10 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"abstract class A {",
-					//error because a static function cannot be abstract
-					"public static abstract function a():void;",
+					"interface A {",
+					//error because an abstract method may only be defined on an
+					//abstract class (not an interface)
+					"static abstract function get a():String;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -691,11 +700,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=true"
         };
-		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\nFunction does not have a body.\n");
+        compileAndExpectErrors(source, false,false,false, options, "The static attribute may be used only on definitions inside a class.\nThe abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\n");
 	}
 
 	@Test
-    public void testAbstractGetterError_withAllowAbstractClassesEnabled()
+    public void testAbstractStaticSetterOnInterfaceError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -708,9 +717,10 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"abstract class A {",
-					//error because a getter cannot be abstract
-					"public abstract function get a():Object;",
+					"interface A {",
+					//error because an abstract method may only be defined on an
+					//abstract class (not an interface)
+					"static abstract function set a(value:String):void;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -719,11 +729,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=true"
         };
-		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\nFunction does not have a body.\nFunction does not return a value.\n");
+        compileAndExpectErrors(source, false,false,false, options, "The static attribute may be used only on definitions inside a class.\nThe abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\n");
 	}
 
 	@Test
-    public void testAbstractSetterError_withAllowAbstractClassesEnabled()
+    public void testAbstractProtectedMethodNoErrors_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -737,8 +747,7 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         String[] extra = new String[]
         {
 					"abstract class A {",
-					//error because a setter cannot be abstract
-					"public abstract function set a(value:Object):void;",
+					"protected abstract function a():void;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -747,11 +756,13 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=true"
         };
-		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\nFunction does not have a body.\n");
+		File tempASFile = generateTempFile(source);
+		String result = compile(tempASFile, source, false,false,false, options, true);
+		Assert.assertEquals("", result);
 	}
 
 	@Test
-    public void testAbstractVariableError_withAllowAbstractClassesEnabled()
+    public void testAbstractInternalMethodNoErrors_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -765,8 +776,7 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         String[] extra = new String[]
         {
 					"abstract class A {",
-					//error because a variable cannot be abstract
-					"public abstract var a:Object;",
+					"internal abstract function a():void;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -775,11 +785,13 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=true"
         };
-		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\n");
+		File tempASFile = generateTempFile(source);
+		String result = compile(tempASFile, source, false,false,false, options, true);
+		Assert.assertEquals("", result);
 	}
 
 	@Test
-    public void testAbstractStaticVariableError_withAllowAbstractClassesEnabled()
+    public void testAbstractPrivateMethodError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -793,8 +805,8 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         String[] extra = new String[]
         {
 					"abstract class A {",
-					//error because a static variable cannot be abstract
-					"public static abstract var a:Object;",
+					//error because an abstract method cannot be private
+					"private abstract function a():void;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -803,11 +815,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=true"
         };
-		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\n");
+        compileAndExpectErrors(source, false,false,false, options, "Methods that are abstract cannot be declared private.\n");
 	}
 
 	@Test
-    public void testAbstractMethodBodyError_withAllowAbstractClassesEnabled()
+    public void testAbstractFinalClassError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -820,9 +832,8 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"abstract class A {",
-					//error because an abstract method has a body
-					"public abstract function a():void {}",
+                    //error because an abstract class cannot be final
+					"abstract final class A {",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -831,11 +842,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=true"
         };
-		compileAndExpectErrors(source, false,false,false, options, "Method marked abstract must not have a body.\n");
+        compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\n");
 	}
 
 	@Test
-    public void testAbstractClassNewOperatorError_withAllowAbstractClassesEnabled()
+    public void testAbstractFinalMethodError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -845,13 +856,12 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] testCode = new String[]
         {
-					//error because the class is abstract and cannot be
-					//instantiated with new
-					"var obj:A = new A();",
         };
         String[] extra = new String[]
         {
 					"abstract class A {",
+					//error because an abstract method cannot be final
+					"public final abstract function a():void;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -860,11 +870,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=true"
         };
-		compileAndExpectErrors(source, false,false,false, options, "Abstract classes cannot be instantiated with the new operator.\n");
+        compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\nFunction does not have a body.\n");
 	}
 
 	@Test
-    public void testConcreteClassExtendsAbstractNewOperatorNoErrors_withAllowAbstractClassesEnabled()
+    public void testAbstractMethodNotInAbstractClassError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -874,13 +884,13 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] testCode = new String[]
         {
-					"var obj:A = new B();",
         };
         String[] extra = new String[]
         {
-					"abstract class A {",
-					"}",
-					"class B extends A {",
+					"class A {",
+					//error because an abstract method may only be defined on an
+					//abstract class
+					"public abstract function a():void;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -889,13 +899,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=true"
         };
-		File tempASFile = generateTempFile(source);
-		String result = compile(tempASFile, source, false,false,false, options, true);
-		Assert.assertEquals("", result);
+		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\nFunction does not have a body.\n");
 	}
 
 	@Test
-    public void testAbstractClassSuperError_withAllowAbstractClassesEnabled()
+    public void testAbstractStaticMethodNotInAbstractClassError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -908,14 +916,10 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"abstract class A {",
-					"public abstract function a():void;",
-					"}",
-					"class B extends A {",
-					"override public function a():void {",
-					//error because the the super method is abstract
-					"super.a();",
-					"};",
+					"class A {",
+					//error because an abstract method may only be defined on an
+					//abstract class
+					"public static abstract function a():void;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -924,11 +928,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=true"
         };
-		compileAndExpectErrors(source, false,false,false, options, "Call to a possibly undefined method a.\n");
+		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\nFunction does not have a body.\n");
 	}
 
 	@Test
-    public void testAbstractClassNotImplementedError_withAllowAbstractClassesEnabled()
+    public void testAbstractGetterNotInAbstractClassError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -941,12 +945,10 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"abstract class A {",
-					"public abstract function a():void;",
-					"}",
-					"class B extends A {",
-					//error because we did not implement the abstract method in
-					//a concrete subclass
+					"class A {",
+					//error because an abstract getter may only be defined on an
+					//abstract class
+					"public abstract function get a():String;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -955,11 +957,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=true"
         };
-		compileAndExpectErrors(source, false,false,false, options, "Method a in abstract class A not implemented by class B\n");
+		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\nFunction does not have a body.\nFunction does not return a value.\n");
 	}
 
 	@Test
-    public void testAbstractClassNotImplementedErrorOneTimeForTwoConcreteSubclasses_withAllowAbstractClassesEnabled()
+    public void testAbstractSetterNotInAbstractClassError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -972,15 +974,10 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"abstract class A {",
-					"public abstract function a():void;",
-					"}",
-                    "class B extends A {",
-					//error because we did not implement the abstract method in
-					//a concrete subclass
-                    "}",
-                    "class C extends B {",
-                    //no duplicate error here!
+					"class A {",
+					//error because an abstract setter may only be defined on an
+					//abstract class
+					"public abstract function set a(value:String):void;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -989,11 +986,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=true"
         };
-		compileAndExpectErrors(source, false,false,false, options, "Method a in abstract class A not implemented by class B\n");
+		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\nFunction does not have a body.\n");
 	}
 
 	@Test
-    public void testAbstractClassMissingOverrideError_withAllowAbstractClassesEnabled()
+    public void testAbstractStaticGetterNotInAbstractClassError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -1006,12 +1003,10 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"abstract class A {",
-					"public abstract function a():void;",
-					"}",
-					"class B extends A {",
-					//error because we did not use the override keyword
-					"public function a():void {}",
+					"class A {",
+					//error because an abstract getter may only be defined on an
+					//abstract class
+					"public static abstract function get a():String;",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -1020,11 +1015,11 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"-allow-abstract-classes=true"
         };
-		compileAndExpectErrors(source, false,false,false, options, "Overriding a function that is not marked for override\n");
+		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\nFunction does not have a body.\nFunction does not return a value.\n");
 	}
 
 	@Test
-    public void testAbstractClassExtendsAbstractWithoutImplementingNoError_withAllowAbstractClassesEnabled()
+    public void testAbstractStaticSetterNotInAbstractClassError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -1037,11 +1032,734 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         };
         String[] extra = new String[]
         {
-					"abstract class A {",
-					"public abstract function a():void;",
-					"}",
-					"abstract class B extends A {",
-					//we don't want an error for unimplemented methods because
+					"class A {",
+					//error because an abstract setter may only be defined on an
+					//abstract class
+					"public static abstract function set a(value:String):void;",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\nFunction does not have a body.\n");
+	}
+
+	@Test
+    public void testAbstractStaticMethodError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					//error because a static method cannot be abstract
+					"public static abstract function a():void;",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\nFunction does not have a body.\n");
+	}
+
+	@Test
+    public void testAbstractGetterNoError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function get a():String;",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		File tempASFile = generateTempFile(source);
+        String result = compile(tempASFile, source, false,false,false, options, true);
+        Assert.assertEquals("", result);
+	}
+
+	@Test
+    public void testAbstractStaticGetterError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					//error because a static getter cannot be abstract
+					"public static abstract function get a():String;",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\nFunction does not have a body.\nFunction does not return a value.\n");
+	}
+
+	@Test
+    public void testAbstractSetterNoError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function set a(value:String):void;",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		File tempASFile = generateTempFile(source);
+        String result = compile(tempASFile, source, false,false,false, options, true);
+        Assert.assertEquals("", result);
+	}
+
+	@Test
+    public void testAbstractStaticSetterError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					//error because a static setter cannot be abstract
+					"public static abstract function set a(value:String):void;",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\nFunction does not have a body.\n");
+	}
+
+	@Test
+    public void testAbstractVariableError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					//error because a variable cannot be abstract
+					"public abstract var a:Object;",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\n");
+	}
+
+	@Test
+    public void testAbstractStaticVariableError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					//error because a static variable cannot be abstract
+					"public static abstract var a:Object;",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\n");
+	}
+
+	@Test
+    public void testAbstractMethodBodyError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					//error because an abstract method has a body
+					"public abstract function a():void {}",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "Method marked abstract must not have a body.\n");
+	}
+
+	@Test
+    public void testAbstractGetterBodyError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					//error because an abstract getter has a body
+					"public abstract function get a():String {}",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "Method marked abstract must not have a body.\n");
+	}
+
+	@Test
+    public void testAbstractSetterBodyError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					//error because an abstract getter has a body
+					"public abstract function set a(value:String):void {}",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "Method marked abstract must not have a body.\n");
+	}
+
+	@Test
+    public void testAbstractClassNewOperatorError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+					//error because the class is abstract and cannot be
+					//instantiated with new
+					"var obj:A = new A();",
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "Abstract classes cannot be instantiated with the new operator.\n");
+	}
+
+	@Test
+    public void testConcreteClassExtendsAbstractNewOperatorNoErrors_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+					"var obj:A = new B();",
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"}",
+					"class B extends A {",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		File tempASFile = generateTempFile(source);
+		String result = compile(tempASFile, source, false,false,false, options, true);
+		Assert.assertEquals("", result);
+	}
+
+	@Test
+    public void testAbstractClassSuperMethodError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function a():void;",
+					"}",
+					"class B extends A {",
+					"override public function a():void {",
+					//error because the super method is abstract
+					"super.a();",
+					"}",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "Call to a possibly undefined method a.\n");
+	}
+
+	@Test
+    public void testAbstractMethodOverride_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function a():void;",
+					"}",
+					"abstract class B extends A {",
+					//error because the method already exists and is already abstract
+					"override public abstract function a():void;",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "Functions cannot be both abstract and override.\n");
+	}
+
+	@Test
+    public void testAbstractClassSuperGetterError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function get a():String;",
+					"}",
+					"class B extends A {",
+					"override public function get a():String {",
+					//error because the super getter is abstract
+					"return super.a;",
+					"}",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "Access of possibly undefined property a.\n");
+	}
+
+	@Test
+    public void testAbstractClassSuperSetterError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function set a(value:String):void;",
+					"}",
+					"class B extends A {",
+					"override public function set a(value:String):void {",
+					//error because the super setter is abstract
+					"super.a = value;",
+					"}",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "Access of possibly undefined property a.\n");
+	}
+
+	@Test
+    public void testAbstractClassMethodNotImplementedError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function a():void;",
+					"}",
+					"class B extends A {",
+					//error because we did not implement the abstract method in
+					//a concrete subclass
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "Method a in abstract class A not implemented by class B\n");
+	}
+
+	@Test
+    public void testAbstractClassGetterNotImplementedError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function get a():String;",
+					"}",
+					"class B extends A {",
+					//error because we did not implement the abstract getter in
+					//a concrete subclass
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "Method get a in abstract class A not implemented by class B\n");
+	}
+
+	@Test
+    public void testAbstractClassSetterNotImplementedError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function set a(value:String):void;",
+					"}",
+					"class B extends A {",
+					//error because we did not implement the abstract setter in
+					//a concrete subclass
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "Method set a in abstract class A not implemented by class B\n");
+	}
+
+	@Test
+    public void testAbstractClassNotImplementedErrorOneTimeForTwoConcreteSubclasses_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function a():void;",
+					"}",
+                    "class B extends A {",
+					//error because we did not implement the abstract method in
+					//a concrete subclass
+                    "}",
+                    "class C extends B {",
+                    //no duplicate error here!
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "Method a in abstract class A not implemented by class B\n");
+	}
+
+	@Test
+    public void testAbstractMethodMissingOverrideError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function a():void;",
+					"}",
+					"class B extends A {",
+					//error because we did not use the override keyword
+					"public function a():void {}",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "Overriding a function that is not marked for override\n");
+	}
+
+	@Test
+    public void testAbstractGetterMissingOverrideError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function get a():String;",
+					"}",
+					"class B extends A {",
+					//error because we did not use the override keyword
+					"public function get a():String {return null;}",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "Overriding a function that is not marked for override\n");
+	}
+
+	@Test
+    public void testAbstractSetterMissingOverrideError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function set a(value:String):void;",
+					"}",
+					"class B extends A {",
+					//error because we did not use the override keyword
+					"public function set a(value:String):void {}",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		compileAndExpectErrors(source, false,false,false, options, "Overriding a function that is not marked for override\n");
+	}
+
+	@Test
+    public void testAbstractClassExtendsAbstractWithoutImplementingNoError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function a():void;",
+					"public abstract function get b():String;",
+					"public abstract function set b(value:String):void;",
+					"}",
+					"abstract class B extends A {",
+					//we don't want an error for unimplemented methods because
 					//this class is also abstract
 					"}"
         };
@@ -1057,7 +1775,7 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
 	}
 
 	@Test
-    public void testConcreteClassExtendsAbstractExtendsAbstractNotImplementedError_withAllowAbstractClassesEnabled()
+    public void testConcreteClassExtendsAbstractExtendsAbstractMethodNotImplementedError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -1091,7 +1809,75 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
 	}
 
 	@Test
-    public void testConcreteClassExtendsAbstractExtendsAbstractMultipleNotImplementedErrors_withAllowAbstractClassesEnabled()
+    public void testConcreteClassExtendsAbstractExtendsAbstractGetterNotImplementedError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function get a():String;",
+					"}",
+					"abstract class B extends A {",
+					//we don't want an error for unimplemented methods because
+					//this class is also abstract
+					"}",
+					"class C extends B {",
+					//but we do want an error here for unimplemented methods
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "Method get a in abstract class A not implemented by class C\n");
+	}
+
+	@Test
+    public void testConcreteClassExtendsAbstractExtendsAbstractSetterNotImplementedError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function set a(value:String):void;",
+					"}",
+					"abstract class B extends A {",
+					//we don't want an error for unimplemented methods because
+					//this class is also abstract
+					"}",
+					"class C extends B {",
+					//but we do want an error here for unimplemented methods
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "Method set a in abstract class A not implemented by class C\n");
+	}
+
+	@Test
+    public void testConcreteClassExtendsAbstractExtendsAbstractMultipleMethodNotImplementedErrors_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -1111,7 +1897,7 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
 					"public abstract function b():void;",
 					"}",
 					"class C extends B {",
-					//mulitple errors because more than one method is not implemented
+					//multiple errors because more than one method is not implemented
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -1124,7 +1910,73 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
 	}
 
 	@Test
-    public void testAbstractClassExtendsAbstractAndImplementsNoError_withAllowAbstractClassesEnabled()
+    public void testConcreteClassExtendsAbstractExtendsAbstractMultipleGetterNotImplementedErrors_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function get a():String;",
+					"}",
+					"abstract class B extends A {",
+					"public abstract function get b():String;",
+					"}",
+					"class C extends B {",
+					//multiple errors because more than one method is not implemented
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "Method get b in abstract class B not implemented by class C\nMethod get a in abstract class A not implemented by class C\n");
+	}
+
+	@Test
+    public void testConcreteClassExtendsAbstractExtendsAbstractMultipleSetterNotImplementedErrors_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function set a(value:String):void;",
+					"}",
+					"abstract class B extends A {",
+					"public abstract function set b(value:String):void;",
+					"}",
+					"class C extends B {",
+					//multiple errors because more than one method is not implemented
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "Method set b in abstract class B not implemented by class C\nMethod set a in abstract class A not implemented by class C\n");
+	}
+
+	@Test
+    public void testAbstractClassExtendsAbstractAndImplementsMethodNoError_withAllowAbstractClassesEnabled()
     {
         String[] imports = new String[]
         {
@@ -1157,6 +2009,74 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
 		Assert.assertEquals("", result);
 	}
 
+	@Test
+    public void testAbstractClassExtendsAbstractAndImplementsGetterNoError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function get a():String;",
+					"}",
+					"abstract class B extends A {",
+					//it's okay for an abstract subclass to implement any
+					//abstract getters from the superclass
+					"override public function get a():String {return null;}",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		File tempASFile = generateTempFile(source);
+		String result = compile(tempASFile, source, false,false,false, options, true);
+		Assert.assertEquals("", result);
+	}
+
+	@Test
+    public void testAbstractClassExtendsAbstractAndImplementsSetterNoError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+					"abstract class A {",
+					"public abstract function set a(value:String):void;",
+					"}",
+					"abstract class B extends A {",
+					//it's okay for an abstract subclass to implement any
+					//abstract setters from the superclass
+					"override public function set a(value:String):void {}",
+					"}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+					"-allow-abstract-classes=true"
+        };
+		File tempASFile = generateTempFile(source);
+		String result = compile(tempASFile, source, false,false,false, options, true);
+		Assert.assertEquals("", result);
+	}
+
 	@Test
     public void testConcreteClassExtendsAbstractNoError_withAllowAbstractClassesEnabled()
     {
@@ -1173,11 +2093,15 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
         {
 					"abstract class A {",
 					"public abstract function a():void;",
+					"public abstract function get b():String;",
+					"public abstract function set b(value:String):void;",
 					"}",
 					"class B extends A {",
 					//no errors because we've implemented all of the methods
 					//that are abstract
 					"override public function a():void {}",
+					"override public function get b():String {return null;}",
+					"override public function set b(value:String):void {}",
 					"}"
         };
         String source = getAS(imports, declarations, testCode, extra);
@@ -1190,4 +2114,59 @@ public class ASAbstractClassTests extends ASFeatureTestsBase
 		String result = compile(tempASFile, source, false,false,false, options, true);
 		Assert.assertEquals("", result);
 	}
+    
+    @Test
+    public void testAbstractNotAllowedOnInterfaceError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            //error because abstract cannot be used with interfaces (only classes)
+            "abstract interface A {",
+            "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-allow-abstract-classes=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\n");
+    }
+    
+    @Test
+    public void testAbstractNotAllowedOnFunctionNotMethodError_withAllowAbstractClassesEnabled()
+    {
+        String[] imports = new String[]
+        {
+        };
+        String[] declarations = new String[]
+        {
+        };
+        String[] testCode = new String[]
+        {
+        };
+        String[] extra = new String[]
+        {
+            //error because abstract cannot be used with standalone functions
+            //that are not class methods
+            "abstract function a():void {",
+            "}"
+        };
+        String source = getAS(imports, declarations, testCode, extra);
+
+        String[] options = new String[]
+        {
+            "-allow-abstract-classes=true"
+        };
+        compileAndExpectErrors(source, false,false,false, options, "The abstract attribute can only be used on a class definition or a non-static, non-final method defined on an abstract class.\n");
+    }
 }
\ No newline at end of file