Great addition! Love it!

Suggestion: When you add features, it’s a good idea to add a Github issue to 
make it easier to track changes for release notes.

Thanks,
Harbs

> On Jan 24, 2019, at 12:58 AM, [email protected] wrote:
> 
> 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 6a85bc1  compiler: added support for abstract classes in ActionScript
> 6a85bc1 is described below
> 
> commit 6a85bc1cd0c09e4ca07cf221a55ec9dd13e5d63c
> Author: Josh Tynjala <[email protected]>
> AuthorDate: Wed Jan 23 14:51:00 2019 -0800
> 
>    compiler: added support for abstract classes in ActionScript
> 
>    When a developer attempts to instantiate an abstract class with the "new" 
> keyword, the compiler will report an error. This is a compile time check for 
> now, but emitters could hypothetically add runtime checks too.
> 
>    The abstract modifier is allowed on classes only at this time, and trying 
> to use it on other definitions, like interfaces, methods, and variables 
> results in a syntax problem.
> 
>    To enable abstract classes, use the new allow-abstract-classes compiler 
> option. Support for abstract classes is disabled by default, meaning using 
> this experimental new syntax is completely opt-in. Even if the syntax widely 
> adopted, we should keep it disabled by default in the compiler to avoid 
> syntax conflicts when using the compiler for code intelligence with other 
> SDKs. To enable it by default for a particular SDK, modify the appropriate 
> frameworks/*-config.xml file.
> 
>    Behind the scenes, When the "abstract" keyword is encountered as a 
> modifier on a class, [RoyaleAbstract] metadata is created. This allows 
> bytecode to store whether a class is abstract, without actually having to 
> update the bytecode format and runtimes that support it. The metadata also 
> allows classes in libraries to remain abstract when compiled to SWC.
> ---
> .../apache/royale/compiler/common/ASModifier.java  |  8 +++-
> .../royale/compiler/config/Configuration.java      | 22 +++++++++++
> .../compiler/constants/IASKeywordConstants.java    |  1 +
> .../royale/compiler/definitions/IDefinition.java   |  7 ++++
> .../royale/compiler/projects/ICompilerProject.java |  5 +++
> .../royale/compiler/internal/parsing/as/ASParser.g |  3 +-
> .../constants/IMetaAttributeConstants.java         |  4 ++
> .../as/codegen/ClassDirectiveProcessor.java        |  9 +++++
> .../as/codegen/GlobalDirectiveProcessor.java       | 19 +++++++++-
> .../as/codegen/InterfaceDirectiveProcessor.java    |  5 +++
> .../internal/definitions/ClassDefinitionBase.java  | 26 +++++++++++++
> .../internal/definitions/DefinitionBase.java       | 24 ++++++++++++
> .../compiler/internal/parsing/as/ASToken.java      |  4 ++
> .../compiler/internal/parsing/as/BaseASParser.java |  3 +-
> .../internal/parsing/as/ConfigProcessor.java       |  6 +++
> .../internal/parsing/as/StreamingASTokenizer.java  |  4 ++
> .../compiler/internal/projects/ASCProject.java     |  6 +++
> .../compiler/internal/projects/RoyaleProject.java  | 15 ++++++++
> .../projects/RoyaleProjectConfigurator.java        |  1 +
> .../semantics/MethodBodySemanticChecker.java       | 11 ++++++
> .../internal/tree/as/BaseDefinitionNode.java       |  2 +
> .../AbstractClassCannotBeInstantiatedProblem.java  | 42 +++++++++++++++++++++
> .../problems/AbstractOutsideClassProblem.java      | 43 ++++++++++++++++++++++
> 23 files changed, 265 insertions(+), 5 deletions(-)
> 
> diff --git 
> a/compiler-common/src/main/java/org/apache/royale/compiler/common/ASModifier.java
>  
> b/compiler-common/src/main/java/org/apache/royale/compiler/common/ASModifier.java
> index bb686ea..a601f80 100644
> --- 
> a/compiler-common/src/main/java/org/apache/royale/compiler/common/ASModifier.java
> +++ 
> b/compiler-common/src/main/java/org/apache/royale/compiler/common/ASModifier.java
> @@ -60,6 +60,11 @@ public class ASModifier
>      * Represents the <code>virtual</code> modifier.
>        */
>       public static final ASModifier VIRTUAL = new 
> ASModifier(IASKeywordConstants.VIRTUAL, 1 << 6);
> +
> +     /**
> +     * Represents the <code>abstract</code> modifier.
> +      */
> +     public static final ASModifier ABSTRACT = new 
> ASModifier(IASKeywordConstants.ABSTRACT, 1 << 7);
>       
>       /**
>        * A list of all the modifiers that exist within AS3
> @@ -71,7 +76,8 @@ public class ASModifier
>               NATIVE,
>               OVERRIDE,
>               STATIC,
> -             VIRTUAL
> +             VIRTUAL,
> +             ABSTRACT
>       };
>       
>     /**
> diff --git 
> a/compiler-common/src/main/java/org/apache/royale/compiler/config/Configuration.java
>  
> b/compiler-common/src/main/java/org/apache/royale/compiler/config/Configuration.java
> index 5f8a3e0..478d346 100644
> --- 
> a/compiler-common/src/main/java/org/apache/royale/compiler/config/Configuration.java
> +++ 
> b/compiler-common/src/main/java/org/apache/royale/compiler/config/Configuration.java
> @@ -1508,6 +1508,28 @@ public class Configuration
>     }
> 
>     //
> +    // 'compiler.allow-abstract-classes' option
> +    //
> +
> +    private boolean allowAbstractClasses = false;
> +
> +    public boolean getCompilerAllowAbstractClasses()
> +    {
> +        return allowAbstractClasses;
> +    }
> +
> +    /**
> +     * Whether the compiler will allow classes to be abstract.
> +     */
> +    @Config
> +    @Mapping({ "compiler", "allow-abstract-classes" })
> +    @RoyaleOnly
> +    public void setCompilerAllowAbstractClasses(ConfigurationValue cv, 
> boolean allow)
> +    {
> +        this.allowAbstractClasses = allow;
> +    }
> +
> +    //
>     // 'compiler.actionscript-file-encoding' option
>     //
> 
> diff --git 
> a/compiler-common/src/main/java/org/apache/royale/compiler/constants/IASKeywordConstants.java
>  
> b/compiler-common/src/main/java/org/apache/royale/compiler/constants/IASKeywordConstants.java
> index b45cea2..54e17ac 100644
> --- 
> a/compiler-common/src/main/java/org/apache/royale/compiler/constants/IASKeywordConstants.java
> +++ 
> b/compiler-common/src/main/java/org/apache/royale/compiler/constants/IASKeywordConstants.java
> @@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableSet;
>  */
> public interface IASKeywordConstants
> {
> +    static final String ABSTRACT = "abstract";
>     static final String AS = "as";
>     static final String BREAK = "break";
>     static final String CASE = "case";
> diff --git 
> a/compiler-common/src/main/java/org/apache/royale/compiler/definitions/IDefinition.java
>  
> b/compiler-common/src/main/java/org/apache/royale/compiler/definitions/IDefinition.java
> index 21f225b..89bfd78 100644
> --- 
> a/compiler-common/src/main/java/org/apache/royale/compiler/definitions/IDefinition.java
> +++ 
> b/compiler-common/src/main/java/org/apache/royale/compiler/definitions/IDefinition.java
> @@ -268,6 +268,13 @@ public interface IDefinition
>     boolean isStatic();
> 
>     /**
> +     * Is this definition marked as <code>abstract</code>?
> +     * 
> +     * @return <code>true</code> if the definition is <code>abstract</code>.
> +     */
> +    boolean isAbstract();
> +
> +    /**
>      * Determines whether the specified modifier is present on this 
> definition.
>      * See {@link ASModifier} for the list of modifiers.
>      * 
> diff --git 
> a/compiler-common/src/main/java/org/apache/royale/compiler/projects/ICompilerProject.java
>  
> b/compiler-common/src/main/java/org/apache/royale/compiler/projects/ICompilerProject.java
> index b3eea14..61d7489 100644
> --- 
> a/compiler-common/src/main/java/org/apache/royale/compiler/projects/ICompilerProject.java
> +++ 
> b/compiler-common/src/main/java/org/apache/royale/compiler/projects/ICompilerProject.java
> @@ -271,5 +271,10 @@ public interface ICompilerProject
>      * @return True if import aliases are allowed.
>      */
>      boolean getAllowImportAliases();
> +     
> +     /**
> +      * @return True if abstract classes are allowed.
> +      */
> +      boolean getAllowAbstractClasses();
> 
> }
> diff --git 
> a/compiler/src/main/antlr/org/apache/royale/compiler/internal/parsing/as/ASParser.g
>  
> b/compiler/src/main/antlr/org/apache/royale/compiler/internal/parsing/as/ASParser.g
> index b4839ce..8a6a299 100644
> --- 
> a/compiler/src/main/antlr/org/apache/royale/compiler/internal/parsing/as/ASParser.g
> +++ 
> b/compiler/src/main/antlr/org/apache/royale/compiler/internal/parsing/as/ASParser.g
> @@ -212,7 +212,7 @@ attributedDefinition[ContainerNode c]
> 
> /**
>  * Matches an attribute such as:
> - * - Modifiers: dynamic, final, native, override, static, virtual.
> + * - Modifiers: dynamic, final, native, override, static, virtual, abstract.
>  * - Namespace names.
>  * - Reserved namespace names: internal, private, public, protected.
>  *
> @@ -580,6 +580,7 @@ modifierAttribute returns [ModifierNode modifierNode]
>         |   TOKEN_MODIFIER_STATIC
>         |   TOKEN_MODIFIER_NATIVE
>         |   TOKEN_MODIFIER_VIRTUAL
> +        |   TOKEN_MODIFIER_ABSTRACT
>         )
>         { modifierNode = new ModifierNode((ASToken) modifierT);       }
>       ;
> diff --git 
> a/compiler/src/main/java/org/apache/royale/compiler/constants/IMetaAttributeConstants.java
>  
> b/compiler/src/main/java/org/apache/royale/compiler/constants/IMetaAttributeConstants.java
> index dee1690..189f8ea 100644
> --- 
> a/compiler/src/main/java/org/apache/royale/compiler/constants/IMetaAttributeConstants.java
> +++ 
> b/compiler/src/main/java/org/apache/royale/compiler/constants/IMetaAttributeConstants.java
> @@ -210,6 +210,9 @@ public interface IMetaAttributeConstants
>     static final String NAME_MIN_VALUE_EXCLUSIVE = "minValueExclusive";
>     static final String NAME_MAX_VALUE = "maxValue";
>     static final String NAME_MAX_VALUE_EXCLUSIVE = "maxValueExclusive";
> +
> +    // [RoyaleAbstract]
> +    static final String ATTRIBUTE_ABSTRACT = "RoyaleAbstract";
>       
>       /**
>        * List of metadata tags that do not inherit
> @@ -222,6 +225,7 @@ public interface IMetaAttributeConstants
>                   ATTRIBUTE_DEPRECATED,
>                   ATTRIBUTE_DISCOURAGED_FOR_PROFILE,
>             ATTRIBUTE_EXCLUDECLASS,
> +            ATTRIBUTE_ABSTRACT,
>         })));
> }
> 
> 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 cc1fef1..ff3a627 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
> @@ -58,6 +58,7 @@ import 
> org.apache.royale.compiler.definitions.IInterfaceDefinition;
> import org.apache.royale.compiler.definitions.metadata.IMetaTag;
> import org.apache.royale.compiler.definitions.metadata.IMetaTagAttribute;
> import org.apache.royale.compiler.exceptions.CodegenInterruptedException;
> +import org.apache.royale.compiler.problems.AbstractOutsideClassProblem;
> import org.apache.royale.compiler.problems.CircularTypeReferenceProblem;
> import 
> org.apache.royale.compiler.problems.ConstructorCannotHaveReturnTypeProblem;
> import org.apache.royale.compiler.problems.ConstructorIsGetterSetterProblem;
> @@ -1091,6 +1092,10 @@ class ClassDirectiveProcessor extends 
> DirectiveProcessor
>             {
>                 classScope.addProblem(new VirtualOutsideClassProblem(site) );
>             }
> +            if( modifiersSet.hasModifier(ASModifier.ABSTRACT) )
> +            {
> +                classScope.addProblem(new AbstractOutsideClassProblem(site) 
> );
> +            }
>         }
>         
> classScope.getMethodBodySemanticChecker().checkForDuplicateModifiers(f);
>         // Functions in a class allow all modifiers
> @@ -1127,6 +1132,10 @@ class ClassDirectiveProcessor extends 
> DirectiveProcessor
>             {
>                 classScope.addProblem(new VirtualOutsideClassProblem(site));
>             }
> +            else if( modifier == ASModifier.ABSTRACT )
> +            {
> +                classScope.addProblem(new AbstractOutsideClassProblem(site));
> +            }
>         }
>         
> classScope.getMethodBodySemanticChecker().checkForDuplicateModifiers(v);
>     }
> diff --git 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/GlobalDirectiveProcessor.java
>  
> b/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/GlobalDirectiveProcessor.java
> index 0f4f3c8..ca63800 100644
> --- 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/GlobalDirectiveProcessor.java
> +++ 
> b/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/GlobalDirectiveProcessor.java
> @@ -30,6 +30,7 @@ import org.apache.royale.compiler.tree.as.IASNode;
> import org.apache.royale.compiler.tree.as.IExpressionNode;
> import org.apache.royale.compiler.common.ASModifier;
> import org.apache.royale.compiler.common.ModifiersSet;
> +import org.apache.royale.compiler.constants.IASKeywordConstants;
> import org.apache.royale.compiler.constants.IMetaAttributeConstants;
> import org.apache.royale.compiler.definitions.IDefinition;
> import org.apache.royale.compiler.internal.definitions.ClassDefinition;
> @@ -45,6 +46,7 @@ import 
> org.apache.royale.compiler.internal.tree.as.NamespaceIdentifierNode;
> import org.apache.royale.compiler.internal.tree.as.PackageNode;
> import org.apache.royale.compiler.internal.tree.as.VariableNode;
> import org.apache.royale.compiler.internal.tree.mxml.MXMLDocumentNode;
> +import org.apache.royale.compiler.problems.AbstractOutsideClassProblem;
> import org.apache.royale.compiler.problems.DynamicNotOnClassProblem;
> import org.apache.royale.compiler.problems.EmbedOnlyOnClassesAndVarsProblem;
> import org.apache.royale.compiler.problems.FinalOutsideClassProblem;
> @@ -54,6 +56,7 @@ import 
> org.apache.royale.compiler.problems.NativeNotOnFunctionProblem;
> import org.apache.royale.compiler.problems.NativeVariableProblem;
> import org.apache.royale.compiler.problems.OverrideOutsideClassProblem;
> import org.apache.royale.compiler.problems.StaticOutsideClassProblem;
> +import org.apache.royale.compiler.problems.SyntaxProblem;
> import org.apache.royale.compiler.problems.VirtualOutsideClassProblem;
> import org.apache.royale.compiler.projects.ICompilerProject;
> import org.apache.royale.compiler.tree.mxml.IMXMLDocumentNode;
> @@ -320,6 +323,16 @@ class GlobalDirectiveProcessor extends DirectiveProcessor
>      */
>     protected void verifyClassModifiers(ClassNode c)
>     {
> +        if(!currentScope.getProject().getAllowAbstractClasses() && 
> c.getDefinition().isAbstract())
> +        {
> +            IASNode problemNode = c.getNameExpressionNode();
> +            if (problemNode == null)
> +            {
> +                problemNode = c;
> +            }
> +            currentScope.addProblem(new SyntaxProblem(problemNode, 
> IASKeywordConstants.ABSTRACT));
> +        }
> +
>         ModifiersSet modifiersSet = c.getModifiers();
>         if (modifiersSet == null)
>             return;
> @@ -328,8 +341,8 @@ class GlobalDirectiveProcessor extends DirectiveProcessor
>         IExpressionNode site = c.getNameExpressionNode();
>         for (ASModifier modifier : modifiers)
>         {
> -            // final allowed on a class
> -            if( modifier == ASModifier.FINAL || modifier == 
> ASModifier.DYNAMIC)
> +            // final, dynamic, and abstract allowed on a class
> +            if( modifier == ASModifier.FINAL || modifier == 
> ASModifier.DYNAMIC || modifier == ASModifier.ABSTRACT)
>             {
>                 continue;
>             }
> @@ -408,6 +421,8 @@ class GlobalDirectiveProcessor extends DirectiveProcessor
>             currentScope.addProblem(new OverrideOutsideClassProblem(site));
>         else if( modifier == ASModifier.VIRTUAL )
>             currentScope.addProblem(new VirtualOutsideClassProblem(site));
> +        else if( modifier == ASModifier.ABSTRACT )
> +            currentScope.addProblem(new AbstractOutsideClassProblem(site));
>     }
> 
>     /**
> diff --git 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/InterfaceDirectiveProcessor.java
>  
> b/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/InterfaceDirectiveProcessor.java
> index f564c1b..46cfd3d 100644
> --- 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/InterfaceDirectiveProcessor.java
> +++ 
> b/compiler/src/main/java/org/apache/royale/compiler/internal/as/codegen/InterfaceDirectiveProcessor.java
> @@ -55,6 +55,7 @@ import 
> org.apache.royale.compiler.internal.tree.as.ImportNode;
> import org.apache.royale.compiler.internal.tree.as.InterfaceNode;
> import org.apache.royale.compiler.internal.tree.as.NamespaceIdentifierNode;
> import org.apache.royale.compiler.internal.tree.as.VariableNode;
> +import org.apache.royale.compiler.problems.AbstractOutsideClassProblem;
> import org.apache.royale.compiler.problems.AmbiguousReferenceProblem;
> import org.apache.royale.compiler.problems.CannotExtendClassProblem;
> import org.apache.royale.compiler.problems.ConstructorInInterfaceProblem;
> @@ -456,6 +457,10 @@ public class InterfaceDirectiveProcessor extends 
> DirectiveProcessor
>             {
>                 interfaceScope.addProblem(new 
> VirtualOutsideClassProblem(site));
>             }
> +            else if( modifier == ASModifier.ABSTRACT )
> +            {
> +                interfaceScope.addProblem(new 
> AbstractOutsideClassProblem(site));
> +            }
>             else if ( modifier == ASModifier.DYNAMIC )
>             {
>                 //  Allow this and continue.
> diff --git 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/ClassDefinitionBase.java
>  
> b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/ClassDefinitionBase.java
> index e00eda3..2dcf3ed 100644
> --- 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/ClassDefinitionBase.java
> +++ 
> b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/ClassDefinitionBase.java
> @@ -32,8 +32,10 @@ import org.apache.royale.compiler.definitions.IDefinition;
> import org.apache.royale.compiler.definitions.IInterfaceDefinition;
> import org.apache.royale.compiler.definitions.ITypeDefinition;
> import org.apache.royale.compiler.definitions.metadata.IMetaTag;
> +import org.apache.royale.compiler.definitions.metadata.IMetaTagAttribute;
> import org.apache.royale.compiler.definitions.references.IReference;
> import org.apache.royale.compiler.internal.as.codegen.BindableHelper;
> +import org.apache.royale.compiler.internal.definitions.metadata.MetaTag;
> import org.apache.royale.compiler.internal.projects.CompilerProject;
> import org.apache.royale.compiler.internal.scopes.ASProjectScope;
> import org.apache.royale.compiler.internal.scopes.ASScope;
> @@ -536,6 +538,30 @@ public abstract class ClassDefinitionBase extends 
> TypeDefinitionBase implements
>         return interfaces;
>     }
> 
> +    @Override
> +    public boolean isAbstract()
> +    {
> +        if(super.isAbstract())
> +        {
> +            return true;
> +        }
> +        IMetaTag[] metaTags = 
> getMetaTagsByName(IMetaAttributeConstants.ATTRIBUTE_ABSTRACT);
> +        return metaTags != null && metaTags.length > 0;
> +    }
> +
> +    /**
> +     * Utility to mark a definition as abstract. This method should only 
> ever be
> +     * called during construction or initialization of a definition.
> +     */
> +    @Override
> +    public void setAbstract()
> +    {
> +        super.setAbstract();
> +
> +        MetaTag abstractMetaTag = new MetaTag(this, 
> IMetaAttributeConstants.ATTRIBUTE_ABSTRACT, new IMetaTagAttribute[0]);
> +        addMetaTag(abstractMetaTag);
> +    }
> +
>     /*
>      * This inner class implements an iterator that enumerates all of this
>      * ClassDefinition's superclasses. <p> It will stop iterating when it
> diff --git 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/DefinitionBase.java
>  
> b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/DefinitionBase.java
> index 2e4c859..a219328 100644
> --- 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/DefinitionBase.java
> +++ 
> b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/DefinitionBase.java
> @@ -701,6 +701,21 @@ public abstract class DefinitionBase implements 
> IDocumentableDefinition, IDefini
>         flags |= FLAG_STATIC;
>     }
> 
> +    // instead of increasing the size of "flags" from a short to int, I added
> +    // a boolean variable instead. feel free to change this, if desired. -JT
> +    private boolean abstractFlag = false;
> +
> +    @Override
> +    public boolean isAbstract()
> +    {
> +        return abstractFlag;
> +    }
> +
> +    public void setAbstract()
> +    {
> +        abstractFlag = true;
> +    }
> +
>     @Override
>     public boolean hasModifier(ASModifier modifier)
>     {
> @@ -731,6 +746,10 @@ public abstract class DefinitionBase implements 
> IDocumentableDefinition, IDefini
>             // Ignore "virtual" modifier.
>             return false;
>         }
> +        else if (modifier == ASModifier.ABSTRACT)
> +        {
> +            return abstractFlag;
> +        }
>         else
>         {
>             assert false : "Unknown modifier: " + modifier;
> @@ -752,6 +771,8 @@ public abstract class DefinitionBase implements 
> IDocumentableDefinition, IDefini
>             result.addModifier(ASModifier.DYNAMIC);
>         if ((flags & FLAG_NATIVE) != 0)
>             result.addModifier(ASModifier.NATIVE);
> +        if (abstractFlag)
> +            result.addModifier(ASModifier.ABSTRACT);
>         return result;
>     }
> 
> @@ -774,6 +795,9 @@ public abstract class DefinitionBase implements 
> IDocumentableDefinition, IDefini
>         else if (modifier == ASModifier.NATIVE)
>             flags |= FLAG_NATIVE;
> 
> +        else if (modifier == ASModifier.ABSTRACT)
> +            setAbstract();
> +
>         else
>             assert false;
>     }
> diff --git 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ASToken.java
>  
> b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ASToken.java
> index 52f2040..fa8b149 100644
> --- 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ASToken.java
> +++ 
> b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ASToken.java
> @@ -463,6 +463,7 @@ public class ASToken extends TokenBase implements 
> IASToken, ASTokenTypes
>             case TOKEN_MODIFIER_NATIVE:
>             case TOKEN_MODIFIER_OVERRIDE:
>             case TOKEN_MODIFIER_STATIC:
> +            case TOKEN_MODIFIER_ABSTRACT:
>                 return true;
>         }
>         return false;
> @@ -514,6 +515,7 @@ public class ASToken extends TokenBase implements 
> IASToken, ASTokenTypes
>             case TOKEN_MODIFIER_OVERRIDE:
>             case TOKEN_MODIFIER_STATIC:
>             case TOKEN_MODIFIER_VIRTUAL:
> +            case TOKEN_MODIFIER_ABSTRACT:
>             case TOKEN_RESERVED_WORD_GET:
>             case TOKEN_RESERVED_WORD_SET:
>             case TOKEN_RESERVED_WORD_NAMESPACE:
> @@ -655,6 +657,7 @@ public class ASToken extends TokenBase implements 
> IASToken, ASTokenTypes
>             case TOKEN_MODIFIER_NATIVE:
>             case TOKEN_MODIFIER_OVERRIDE:
>             case TOKEN_MODIFIER_STATIC:
> +            case TOKEN_MODIFIER_ABSTRACT:
>                 return true;
>         }
>         return false;
> @@ -918,6 +921,7 @@ public class ASToken extends TokenBase implements 
> IASToken, ASTokenTypes
>             case TOKEN_MODIFIER_NATIVE:
>             case TOKEN_MODIFIER_OVERRIDE:
>             case TOKEN_MODIFIER_STATIC:
> +            case TOKEN_MODIFIER_ABSTRACT:
>                 return ASTokenKind.MODIFIER;
>             case HIDDEN_TOKEN_BUILTIN_NS:
>             case TOKEN_NAMESPACE_ANNOTATION:
> diff --git 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/BaseASParser.java
>  
> b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/BaseASParser.java
> index a8c3d7f..c247c89 100644
> --- 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/BaseASParser.java
> +++ 
> b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/BaseASParser.java
> @@ -2329,7 +2329,7 @@ abstract class BaseASParser extends LLkParser 
> implements IProblemReporter
>     }
> 
>     private static final ImmutableSet<String> 
> CONTEXTUAL_RESERVED_KEYWORD_MODIFIERS =
> -            ImmutableSet.of("dynamic", "final", "native", "static", 
> "override");
> +            ImmutableSet.of("dynamic", "final", "native", "static", 
> "override", "abstract");
> 
>     /**
>      * Recover from {@link CanNotInsertSemicolonProblem} after an expression
> @@ -2854,6 +2854,7 @@ abstract class BaseASParser extends LLkParser 
> implements IProblemReporter
>                 case TOKEN_MODIFIER_OVERRIDE:
>                 case TOKEN_MODIFIER_STATIC:
>                 case TOKEN_MODIFIER_VIRTUAL:
> +                case TOKEN_MODIFIER_ABSTRACT:
>                     return true;
>             }
>         }
> diff --git 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ConfigProcessor.java
>  
> b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ConfigProcessor.java
> index 1cf7922..af2dd3b 100644
> --- 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ConfigProcessor.java
> +++ 
> b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ConfigProcessor.java
> @@ -164,6 +164,12 @@ public class ConfigProcessor
>                       // TODO Auto-generated method stub
>                       return false;
>               }
> +
> +             @Override
> +             public boolean getAllowAbstractClasses() {
> +                     // TODO Auto-generated method stub
> +                     return false;
> +             }
>     }
> 
>     /**
> diff --git 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/StreamingASTokenizer.java
>  
> b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/StreamingASTokenizer.java
> index 2cb8e99..32017a4 100644
> --- 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/StreamingASTokenizer.java
> +++ 
> b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/StreamingASTokenizer.java
> @@ -101,6 +101,7 @@ public class StreamingASTokenizer implements 
> ASTokenTypes, IASTokenizer, Closeab
>             .put(IASKeywordConstants.OVERRIDE, TOKEN_MODIFIER_OVERRIDE)
>             .put(IASKeywordConstants.STATIC, TOKEN_MODIFIER_STATIC)
>             .put(IASKeywordConstants.VIRTUAL, TOKEN_MODIFIER_VIRTUAL)
> +            .put(IASKeywordConstants.ABSTRACT, TOKEN_MODIFIER_ABSTRACT)
>             .put(IASKeywordConstants.SET, TOKEN_RESERVED_WORD_SET)
>             // Keywords with special token types that affect subsequent blocks
>             .put(IASKeywordConstants.CATCH, TOKEN_KEYWORD_CATCH)
> @@ -917,6 +918,7 @@ public class StreamingASTokenizer implements 
> ASTokenTypes, IASTokenizer, Closeab
>                 case TOKEN_MODIFIER_OVERRIDE:
>                 case TOKEN_MODIFIER_STATIC:
>                 case TOKEN_MODIFIER_VIRTUAL:
> +                case TOKEN_MODIFIER_ABSTRACT:
>                 {
>                     // previous token is either a modifier or a namespace, or 
> if
>                     // null, assume keyword
> @@ -938,6 +940,7 @@ public class StreamingASTokenizer implements 
> ASTokenTypes, IASTokenizer, Closeab
>                             case TOKEN_MODIFIER_OVERRIDE:
>                             case TOKEN_MODIFIER_STATIC:
>                             case TOKEN_MODIFIER_VIRTUAL:
> +                            case TOKEN_MODIFIER_ABSTRACT:
>                             case TOKEN_NAMESPACE_ANNOTATION:
>                             case TOKEN_NAMESPACE_NAME:
>                             case HIDDEN_TOKEN_BUILTIN_NS:
> @@ -1773,6 +1776,7 @@ public class StreamingASTokenizer implements 
> ASTokenTypes, IASTokenizer, Closeab
>                 case TOKEN_MODIFIER_OVERRIDE:
>                 case TOKEN_MODIFIER_STATIC:
>                 case TOKEN_MODIFIER_VIRTUAL:
> +                case TOKEN_MODIFIER_ABSTRACT:
>                 case TOKEN_KEYWORD_CLASS:
>                 case TOKEN_KEYWORD_INTERFACE:
>                 case TOKEN_NAMESPACE_ANNOTATION:
> diff --git 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/ASCProject.java
>  
> b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/ASCProject.java
> index d229ca3..de04bb2 100644
> --- 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/ASCProject.java
> +++ 
> b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/ASCProject.java
> @@ -86,4 +86,10 @@ public class ASCProject extends CompilerProject implements 
> IASCProject
>               // TODO Auto-generated method stub
>               return false;
>       }
> +
> +     @Override
> +     public boolean getAllowAbstractClasses() {
> +             // TODO Auto-generated method stub
> +             return false;
> +     }
> }
> diff --git 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
>  
> b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
> index 6a03191..c99f5bb 100644
> --- 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
> +++ 
> b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
> @@ -2445,6 +2445,21 @@ public class RoyaleProject extends ASProject 
> implements IRoyaleProject, ICompile
>       allowImportAliases = allow;
>     }
> 
> +    private boolean allowAbstractClasses = false;
> +    
> +    /**
> +     * Indicates if abstract classes are allowed.
> +     */
> +    @Override
> +    public boolean getAllowAbstractClasses()
> +    {
> +     return allowAbstractClasses;
> +    }
> +    public void setAllowAbstractClasses(boolean allow)
> +    {
> +     allowAbstractClasses = allow;
> +    }
> +
>       @Override
>       public boolean isPlatformRule(ICSSRule rule) {
>               return true;
> diff --git 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProjectConfigurator.java
>  
> b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProjectConfigurator.java
> index 409dfd9..cb3a35b 100644
> --- 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProjectConfigurator.java
> +++ 
> b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProjectConfigurator.java
> @@ -264,6 +264,7 @@ public class RoyaleProjectConfigurator extends 
> Configurator
>             
> project.setAllowPrivateNameConflicts(configuration.getCompilerAllowPrivateNameConflicts());
> 
>             
> project.setAllowImportAliases(configuration.getCompilerAllowImportAliases());
> +            
> project.setAllowAbstractClasses(configuration.getCompilerAllowAbstractClasses());
> 
>             DataTranscoder.embedClassName = 
> configuration.getByteArrayEmbedClass();
>         }
> 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 0e009fe..c142116 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
> @@ -2089,6 +2089,13 @@ public class MethodBodySemanticChecker
>         {
>             ClassDefinition class_def = (ClassDefinition)def;
> 
> +            if ( project.getAllowAbstractClasses() && class_def.isAbstract() 
> )
> +            {
> +                addProblem(new AbstractClassCannotBeInstantiatedProblem(
> +                    roundUpUsualSuspects(class_binding, iNode)
> +                ));
> +            }
> +
>             IFunctionDefinition ctor = class_def.getConstructor();
> 
>             if ( ctor instanceof FunctionDefinition )
> @@ -2456,6 +2463,10 @@ public class MethodBodySemanticChecker
>                 {
>                     currentScope.addProblem(new 
> StaticOutsideClassProblem(site));
>                 }
> +                else if( modifier == ASModifier.ABSTRACT )
> +                {
> +                    currentScope.addProblem(new 
> AbstractOutsideClassProblem(site));
> +                }
>             }
>         }
> 
> diff --git 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/BaseDefinitionNode.java
>  
> b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/BaseDefinitionNode.java
> index a1d9609..c45def6 100644
> --- 
> a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/BaseDefinitionNode.java
> +++ 
> b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/BaseDefinitionNode.java
> @@ -401,6 +401,8 @@ public abstract class BaseDefinitionNode extends TreeNode 
> implements IDocumentab
>             db.setOverride();
>         if (hasModifier(ASModifier.STATIC))
>             db.setStatic();
> +        if (hasModifier(ASModifier.ABSTRACT))
> +            db.setAbstract();
>     }
> 
>     protected void fillInMetadata(DefinitionBase definition)
> diff --git 
> a/compiler/src/main/java/org/apache/royale/compiler/problems/AbstractClassCannotBeInstantiatedProblem.java
>  
> b/compiler/src/main/java/org/apache/royale/compiler/problems/AbstractClassCannotBeInstantiatedProblem.java
> new file mode 100644
> index 0000000..e9d34d1
> --- /dev/null
> +++ 
> b/compiler/src/main/java/org/apache/royale/compiler/problems/AbstractClassCannotBeInstantiatedProblem.java
> @@ -0,0 +1,42 @@
> +/*
> + *
> + *  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;
> +
> +/**
> + *  Semantics diagnostic emitted when the method body
> + *  semantic checker detects an attempt to instantiate an abstract class.
> + */
> +public final class AbstractClassCannotBeInstantiatedProblem extends 
> SemanticProblem
> +{
> +    public static final String DESCRIPTION =
> +        "Abstract classes cannot be instantiated with the ${NEW} operator.";
> +
> +    public static final int errorCode = 1156;
> +
> +    public AbstractClassCannotBeInstantiatedProblem(IASNode site)
> +    {
> +        super(site);
> +    }
> +    
> +    // Prevent these from being localized.
> +    public final String NEW = "new";
> +}
> diff --git 
> a/compiler/src/main/java/org/apache/royale/compiler/problems/AbstractOutsideClassProblem.java
>  
> b/compiler/src/main/java/org/apache/royale/compiler/problems/AbstractOutsideClassProblem.java
> new file mode 100644
> index 0000000..4fea9f1
> --- /dev/null
> +++ 
> b/compiler/src/main/java/org/apache/royale/compiler/problems/AbstractOutsideClassProblem.java
> @@ -0,0 +1,43 @@
> +/*
> + *
> + *  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;
> +
> +/**
> + * Problem generated when 'abstract' is used outside of a class
> + */
> +public final class AbstractOutsideClassProblem extends CodegenProblem
> +{
> +    // TODO ErrorMSG: not specific to methods
> +    public static final String DESCRIPTION =
> +            "The ${ABSTRACT} attribute may be used only ${CLASS} property 
> definitions.";
> +
> +    public static final int errorCode = 1011;
> +
> +    public AbstractOutsideClassProblem(IASNode site)
> +    {
> +        super(site);
> +    }
> +
> +    // Prevent these from being localized.
> +    public final String ABSTRACT = "abstract";
> +    public final String CLASS = "class";
> +}
> 


Reply via email to