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>*
