So cool! :) Think is time to tweet it! :)
El jue., 24 ene. 2019 a las 16:50, Harbs (<[email protected]>) escribió: > 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>* > >> > > > -- Carlos Rovira http://about.me/carlosrovira
