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 <[email protected]>
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


Reply via email to