Great addition Josh! I think this deserves a good tweet about it! :)
El jue., 24 ene. 2019 a las 10:13, Piotr Zarzycki (< [email protected]>) escribió: > 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
