Perfect! Thanks!

> On Jan 24, 2019, at 5:39 PM, Josh Tynjala <[email protected]> wrote:
> 
> Following the suggestion from Harbs, I created a Github issue for abstract 
> classes:
> 
> https://github.com/apache/royale-compiler/issues/73
> 
> There's a code example in the description.
> 
> - Josh
> 
> On 2019/01/24 09:13:34, Piotr Zarzycki <[email protected]> wrote: 
>> Wow! <3
>> How does that class looks like ? Is it follow similar principle as it is in
>> C# language ?
>> 
>> czw., 24 sty 2019 o 10:09 Harbs <[email protected]> napisał(a):
>> 
>>> 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";
>>>> +}
>>>> 
>>> 
>>> 
>>> 
>> 
>> -- 
>> 
>> Piotr Zarzycki
>> 
>> Patreon: *https://www.patreon.com/piotrzarzycki
>> <https://www.patreon.com/piotrzarzycki>*
>> 


Reply via email to