]> source.dussan.org Git - aspectj.git/commitdiff
Autoboxing and decp restrictions
authoraclement <aclement>
Fri, 10 Dec 2004 13:34:42 +0000 (13:34 +0000)
committeraclement <aclement>
Fri, 10 Dec 2004 13:34:42 +0000 (13:34 +0000)
15 files changed:
org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AspectJBuilder.java
org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/ajc/BuildArgParserTestCase.java
weaver/src/org/aspectj/weaver/Lint.java
weaver/src/org/aspectj/weaver/ResolvedTypeX.java
weaver/src/org/aspectj/weaver/TypeX.java
weaver/src/org/aspectj/weaver/World.java
weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
weaver/src/org/aspectj/weaver/bcel/Utility.java
weaver/src/org/aspectj/weaver/patterns/DeclareParents.java

index f3aad92149d90f1f46127078046159f248f967d1..e383fb4588f4c955136b4900c5c38f16a7c40bd0 100644 (file)
@@ -612,6 +612,21 @@ public class BuildArgParser extends Main {
                buildConfig.setProceedOnError(true);
             } else if (new File(arg).isDirectory()) {
                 showError("dir arg not permitted: " + arg);
+            } else if (arg.equals("-1.5")) {
+               buildConfig.setBehaveInJava5Way(true);
+// this would enable the '-source 1.5' to do the same as '-1.5' but doesnt sound quite right as
+// as an option right now as it doesnt mean we support 1.5 source code - people will get confused...
+//            } else if (arg.equals("-source")) {
+//             if (args.size() > nextArgIndex) {
+//                     String level = ((ConfigParser.Arg)args.get(nextArgIndex)).getValue();
+//                     if (!level.equals("1.5")) {
+//                             unparsedArgs.add("-source");
+//                             unparsedArgs.add(level);
+//                     } else {
+//                             buildConfig.setJava5Behaviour(true);
+//                     }
+//                     args.remove(args.get(nextArgIndex));
+//             }
                        } else {
                 // argfile, @file parsed by superclass
                 // no eclipse options parsed:
index 0dd92150a4ecb1240bc935c8f0ddc364154af325..061417143fd2db4582324caaf23eeaae3b4940a5 100644 (file)
@@ -55,6 +55,7 @@ Standard Eclipse compiler options:\n\
 \ Compliance options:\n\
 \    -1.3               use 1.3 compliance level (implicit -source 1.3 -target 1.1)\n\
 \    -1.4             + use 1.4 compliance level (implicit -source 1.3 -target 1.2)\n\
+\    -1.5               set behaviour of the weaver to 1.5 mode\n\
 \    -source <version>  set source level (1.3 or 1.4)\n\
 \    -target <version>  set classfile target (1.1 to 1.4)\n\
 \ \n\
index da778a54e98120e3cbabe7c032e567af5bfb78bc..8306dd12030d6c4f108e26832bcf63a61cefaba8 100644 (file)
@@ -416,7 +416,7 @@ public class AjLookupEnvironment extends LookupEnvironment {
        }
        
        private void doDeclareParents(DeclareParents declareParents, SourceTypeBinding sourceType) {
-               List newParents = declareParents.findMatchingNewParents(factory.fromEclipse(sourceType));
+               List newParents = declareParents.findMatchingNewParents(factory.fromEclipse(sourceType),false);
                if (!newParents.isEmpty()) {
                        for (Iterator i = newParents.iterator(); i.hasNext(); ) {
                                ResolvedTypeX parent = (ResolvedTypeX)i.next();
index 562a5951bf974302fd573d1851b6345732462e45..12ca5f606aee4ef4251acdb52d823f63f6e08b87 100644 (file)
@@ -524,4 +524,12 @@ public class AjBuildConfig {
        public boolean getProceedOnError() {
                return options.proceedOnError;
        }
+
+       public void setBehaveInJava5Way(boolean b) {
+               options.behaveInJava5Way = b;
+       }
+       
+       public boolean getBehaveInJava5Way() {
+               return options.behaveInJava5Way;
+       }
 }
index a08d1c0ef67fe8578863305e04a94dba3c7dd092..d0701d190eedc0c9df4fbb29e3a1e2dfb4c73d48 100644 (file)
@@ -489,6 +489,7 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
                List cp = buildConfig.getBootclasspath();
                cp.addAll(buildConfig.getClasspath());
                bcelWorld = new BcelWorld(cp, handler, null);
+               bcelWorld.setBehaveInJava5Way(buildConfig.getBehaveInJava5Way());
                bcelWorld.setXnoInline(buildConfig.isXnoInline());
                bcelWorld.setXlazyTjp(buildConfig.isXlazyTjp());
                bcelWeaver = new BcelWeaver(bcelWorld);
index 9049547218203dda04645e49286a44038a7ead08..8553ed9dfff152524807b5085ac9c79ece0a0197 100644 (file)
@@ -66,6 +66,9 @@ public class AjCompilerOptions extends CompilerOptions {
        public boolean xReweavableCompress = false;
        public boolean showWeavingInformation = false;
        
+       // If true - autoboxing behaves differently ...
+       public boolean behaveInJava5Way = false;
+       
        // these next three not exposed by IDEs
        public boolean generateModel = false;
        public boolean generateJavaDocsInModel = false;
index a1e066b79eafe48db3d77ccf4332775ba802db43..b91aed439bbd7b57d5a3a06e3e23cc603e359a39 100644 (file)
@@ -154,6 +154,7 @@ public class AspectJBuilder extends JavaBuilder implements ICompilerAdapterFacto
        private void initWorldAndWeaver(AjCompilerOptions options) {
                cpManager = new EclipseClassPathManager(nameEnvironment);
                myBcelWorld = new BcelWorld(cpManager,new UnhandledMessageHandler(getProject()),null /*(xrefHandler)*/);
+               myBcelWorld.setBehaveInJava5Way(options.behaveInJava5Way);
                myBcelWorld.setXnoInline(options.xNoInline);
                myBcelWorld.setXlazyTjp(options.xLazyThisJoinPoint);
                setLintProperties(myBcelWorld,options);
index 238879e7108357e81502d601c44522320066cfb8..a020afe9f341754ddc25ebc41c78526b593bed08 100644 (file)
@@ -422,6 +422,28 @@ public class BuildArgParserTestCase extends TestCase {
                assertTrue(new File(lintFile).exists());
                assertEquals(getCanonicalPath(new File(lintFile)),config.getLintSpecFile().getAbsolutePath());  
        }
+       
+       /**
+        * The option '-1.5' are currently eaten by the AspectJ argument parser - since
+        * the JDT compiler upon which we are based doesn't understand them - *this should change* when we
+        * switch to a 1.5 compiler base.  They are currently used to determine whether the weaver should
+        * behave in a '1.5' way - for example autoboxing behaves differently when the 1.5 flag is specified.
+        * Under 1.4 Integer != int
+        * Under 1.5 Integer == int
+        * (this applies to all primitive types)
+        */
+       public void testSource15() throws InvalidInputException {
+//             AjBuildConfig config = genBuildConfig(new String[]{"-source","1.5"},messageWriter);
+//             assertTrue("should be in 1.5 mode",config.getJave5Behaviour());
+               AjBuildConfig config = genBuildConfig(new String[]{"-1.5"},messageWriter);
+               assertTrue("should be in 1.5 mode",config.getBehaveInJava5Way());
+               config = genBuildConfig(new String[]{"-source","1.4"},messageWriter);
+               assertTrue("should not be in 1.5 mode",!config.getBehaveInJava5Way());
+               assertTrue("should be in 1.4 mode",config.getOptions().sourceLevel == CompilerOptions.JDK1_4);
+               config = genBuildConfig(new String[]{"-source","1.3"},messageWriter);
+               assertTrue("should not be in 1.5 mode",!config.getBehaveInJava5Way());
+               assertTrue("should be in 1.3 mode",config.getOptions().sourceLevel == CompilerOptions.JDK1_3);
+       }
 
        public void testOptions() throws InvalidInputException {
 //             AjdtCommand command = new AjdtCommand();
index 466cf9b5bc2a07d72e29d1c9f32b94fcf91fa1f8..942aab18226312622f1047a825dc720b38dd50ed 100644 (file)
@@ -65,6 +65,12 @@ public class Lint {
        public final Kind noJoinpointsForBridgeMethods =
                new Kind("noJoinpointsForBridgeMethods","pointcut did not match on the method call to a bridge method.  Bridge methods are generated by the compiler and have no join points");
        
+       public final Kind enumAsTargetForDecpIgnored =
+               new Kind("enumAsTargetForDecpIgnored","enum type {0} matches a declare parents type pattern but is being ignored");
+
+       public final Kind annotationAsTargetForDecpIgnored =
+               new Kind("annotationAsTargetForDecpIgnored","annotation type {0} matches a declare parents type pattern but is being ignored");
+       
        public final Kind cantMatchArrayTypeOnVarargs =
                new Kind("cantMatchArrayTypeOnVarargs","an array type as the last parameter in a signature does not match on the varargs declared method: {0}");
        
index f324affae008ca2a31908415764496453052289b..b2a0b116cace9bce4f1182e2d6216491e2045658 100644 (file)
@@ -18,8 +18,10 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 
 import org.aspectj.bridge.IMessage;
 import org.aspectj.bridge.ISourceLocation;
@@ -99,11 +101,42 @@ public abstract class ResolvedTypeX extends TypeX implements AnnotatedElement {
     public boolean needsNoConversionFrom(TypeX other, World world) {
         return needsNoConversionFrom(other);
     }
+    
+    // This set contains pairs of types whose signatures are concatenated
+    // together, this means with a fast lookup we can tell if two types
+    // are equivalent.
+    private static Set validBoxing = new HashSet();
+    
+    static {
+      validBoxing.add("Ljava/lang/Byte;B");
+      validBoxing.add("Ljava/lang/Character;C");
+      validBoxing.add("Ljava/lang/Double;D");
+      validBoxing.add("Ljava/lang/Float;F");
+      validBoxing.add("Ljava/lang/Integer;I");
+      validBoxing.add("Ljava/lang/Long;J");
+      validBoxing.add("Ljava/lang/Short;S");
+      validBoxing.add("Ljava/lang/Boolean;Z");
+      validBoxing.add("BLjava/lang/Byte;");
+      validBoxing.add("CLjava/lang/Character;");
+      validBoxing.add("DLjava/lang/Double;");
+      validBoxing.add("FLjava/lang/Float;");
+      validBoxing.add("ILjava/lang/Integer;");
+      validBoxing.add("JLjava/lang/Long;");
+      validBoxing.add("SLjava/lang/Short;");
+      validBoxing.add("ZLjava/lang/Boolean;");
+    }
+    
     public final boolean isConvertableFrom(TypeX other) {
         if (this.equals(OBJECT) || other.equals(OBJECT)) return true;
+        if (world.behaveInJava5Way) {
+               if (this.isPrimitive()^other.isPrimitive()) { // If one is primitive and the other isnt
+                       if (validBoxing.contains(this.getSignature()+other.getSignature())) return true;
+               }
+        }
         return this.isCoerceableFrom(other);
     }
     
+
     // utilities                
     public ResolvedTypeX getResolvedComponentType() {
        return null;
@@ -595,7 +628,10 @@ public abstract class ResolvedTypeX extends TypeX implements AnnotatedElement {
         }
             
         public final boolean isAssignableFrom(TypeX o) {
-            if (o.isPrimitive()) return false;
+               if (o.isPrimitive()) {
+                       if (!world.behaveInJava5Way) return false;
+                       if (validBoxing.contains(this.getSignature()+o.getSignature())) return true;
+               }
             ResolvedTypeX other = o.resolve(world);
 
             return isAssignableFrom(other);
@@ -879,7 +915,10 @@ public abstract class ResolvedTypeX extends TypeX implements AnnotatedElement {
                return false;
         }
         public final boolean isAssignableFrom(TypeX other) {
-            if (! other.isPrimitive()) return false;
+            if (!other.isPrimitive()) {
+               if (!world.behaveInJava5Way) return false;
+               return validBoxing.contains(this.getSignature()+other.getSignature());
+            }
             return assignTable[((Primitive)other).index][index];
         }
         public final boolean isCoerceableFrom(TypeX other) {
index 6a44d338c0da0c99e673d145a0a1ff1c2405f712..c13349eb351d1c4abc52054879ca0a1d47734879 100644 (file)
@@ -368,7 +368,7 @@ public class TypeX implements AnnotatedElement {
     public boolean isAssignableFrom(TypeX other, World world) {
                // primitives override this method, so we know we're not primitive.
                // So if the other is primitive, don't bother asking the world anything.
-               if (other.isPrimitive()) return false;
+               if (other.isPrimitive() && !world.behaveInJava5Way) return false;
         return world.isAssignableFrom(this, other);
     }
 
@@ -582,6 +582,9 @@ public class TypeX implements AnnotatedElement {
     public static final TypeX   ERROR    = forSignature("Ljava/lang/Error;");    
     public static final TypeX   AT_INHERITED = forSignature("Ljava/lang/annotation/Inherited;");
     public static final TypeX   AT_RETENTION = forSignature("Ljava/lang/annotation/Retention;");
+    public static final TypeX   ENUM         = forSignature("Ljava/lang/Enum;");
+    public static final TypeX   ANNOTATION   = forSignature("Ljava/lang/annotation/Annotation;");
+
     
     // ---- helpers
     
index 74a08305374505a62b4b191e0e625c9e5a102911..228eeb3f1e36d59911a5ad0e2a18f400e566a768 100644 (file)
@@ -44,7 +44,10 @@ public abstract class World implements Dump.INode {
     
     protected boolean XnoInline;
     protected boolean XlazyTjp;
+
+    public boolean behaveInJava5Way = false;
     
+
     private List dumpState_cantFindTypeExceptions = null;
        
     protected World() {
@@ -118,7 +121,7 @@ public abstract class World implements Dump.INode {
        //System.out.println("resolve: " + ty + " world " + typeMap.keySet());
         String signature = ty.getSignature();
         ResolvedTypeX ret = typeMap.get(signature);
-        if (ret != null) return ret;
+        if (ret != null) { ret.world = this; return ret; } // Set the world for the RTX
         
         if (ty.isArray()) {
             ret = new ResolvedTypeX.Array(signature, this, resolve(ty.getComponentType(), allowMissing));
@@ -158,7 +161,7 @@ public abstract class World implements Dump.INode {
     }
 
     protected final boolean isAssignableFrom(TypeX type, TypeX other) {
-        return resolve(type).isAssignableFrom(other);
+        return resolve(type).isAssignableFrom(resolve(other));
     }
 
     public boolean needsNoConversionFrom(TypeX type, TypeX other) {
@@ -519,4 +522,8 @@ public abstract class World implements Dump.INode {
                                        );
                }
        }       
+       
+       public void setBehaveInJava5Way(boolean b) {
+       behaveInJava5Way = b;
+    }
 }
index 3e497642d966936b94410a1aea50270531ad0acf..1f850999e026d0d2e30ae329bdabe0c46afa0666 100644 (file)
@@ -673,7 +673,7 @@ public class BcelWeaver implements IWeaver {
                // need to do any declare parents before the matching below
                for (Iterator i = declareParentsList.iterator(); i.hasNext(); ) {
                        DeclareParents p = (DeclareParents)i.next();
-                       List newParents = p.findMatchingNewParents(onType);
+                       List newParents = p.findMatchingNewParents(onType,true);
                        if (!newParents.isEmpty()) {
                                BcelObjectType classType = BcelWorld.getBcelObjectType(onType);
                                //System.err.println("need to do declare parents for: " + onType);
index 0a98a098530f7e6b931cb7390ac50ad25d865f75..64c512f91855413553cfdc05a05a57ec5863e223 100644 (file)
@@ -18,6 +18,9 @@ import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
 
 import org.aspectj.apache.bcel.Constants;
 import org.aspectj.apache.bcel.classfile.ClassParser;
@@ -206,6 +209,29 @@ public class Utility {
         return ret;
     }
     
+    // Lookup table, for converting between pairs of types, it gives
+    // us the method name in the Conversions class
+    private static Hashtable validBoxing = new Hashtable();
+    
+    static {
+      validBoxing.put("Ljava/lang/Byte;B","byteObject");
+      validBoxing.put("Ljava/lang/Character;C","charObject");
+      validBoxing.put("Ljava/lang/Double;D","doubleObject");
+      validBoxing.put("Ljava/lang/Float;F","floatObject");
+      validBoxing.put("Ljava/lang/Integer;I","intObject");
+      validBoxing.put("Ljava/lang/Long;J","longObject");
+      validBoxing.put("Ljava/lang/Short;S","shortObject");
+      validBoxing.put("Ljava/lang/Boolean;Z","booleanObject");
+      validBoxing.put("BLjava/lang/Byte;","byteValue");
+      validBoxing.put("CLjava/lang/Character;","charValue");
+      validBoxing.put("DLjava/lang/Double;","doubleValue");
+      validBoxing.put("FLjava/lang/Float;","floatValue");
+      validBoxing.put("ILjava/lang/Integer;","intValue");
+      validBoxing.put("JLjava/lang/Long;","longValue");
+      validBoxing.put("SLjava/lang/Short;","shortValue");
+      validBoxing.put("ZLjava/lang/Boolean;","booleanValue");
+    }
+    
     public static void appendConversion(
         InstructionList il,
         InstructionFactory fact,
@@ -215,8 +241,12 @@ public class Utility {
         if (! toType.isConvertableFrom(fromType)) {
             throw new BCException("can't convert from " + fromType + " to " + toType);
         }
-        if (toType.needsNoConversionFrom(fromType)) return;
-
+           // XXX I'm sure this test can be simpler but my brain hurts and this works
+        if (!toType.getWorld().behaveInJava5Way) {
+               if (toType.needsNoConversionFrom(fromType)) return;
+        } else {
+               if (toType.needsNoConversionFrom(fromType) && !(toType.isPrimitive()^fromType.isPrimitive())) return;
+        }
         if (toType.equals(ResolvedTypeX.VOID)) {
             // assert fromType.equals(TypeX.OBJECT)
             il.append(InstructionFactory.createPop(fromType.getSize()));
@@ -249,6 +279,29 @@ public class Utility {
                     Type.OBJECT,
                     new Type[] { from },
                     Constants.INVOKESTATIC));
+        } else if (toType.getWorld().behaveInJava5Way && validBoxing.get(toType.getSignature()+fromType.getSignature())!=null) {
+               // XXX could optimize by using any java boxing code that may be just before the call...
+               Type from   = BcelWorld.makeBcelType(fromType);
+               Type to     = BcelWorld.makeBcelType(toType);
+            String name = (String)validBoxing.get(toType.getSignature()+fromType.getSignature());
+            if (toType.isPrimitive()) {
+               il.append(
+                        fact.createInvoke(
+                          "org.aspectj.runtime.internal.Conversions",
+                          name,
+                                                 to,
+                          new Type[]{Type.OBJECT},
+                          Constants.INVOKESTATIC));
+            } else {
+                il.append(
+                  fact.createInvoke(
+                    "org.aspectj.runtime.internal.Conversions",
+                    name,
+                    Type.OBJECT,
+                    new Type[] { from },
+                    Constants.INVOKESTATIC));
+                il.append(fact.createCheckCast((ReferenceType) to));
+            }
         } else if (fromType.isPrimitive()) {
             // assert toType.isPrimitive()
             Type from = BcelWorld.makeBcelType(fromType);
index a5ece09bdc4600f945e2911ce05504f83fa5773d..3adcd722ace753e94f2b4fab22758ef2cfc1543c 100644 (file)
@@ -30,6 +30,7 @@ import org.aspectj.weaver.World;
 public class DeclareParents extends Declare {
        private TypePattern child;
        private TypePatternList parents;
+       private boolean isWildChild = false;
        
 
        public DeclareParents(TypePattern child, List parents) {
@@ -39,6 +40,7 @@ public class DeclareParents extends Declare {
        private DeclareParents(TypePattern child, TypePatternList parents) {
                this.child = child;
                this.parents = parents;
+               if (child instanceof WildTypePattern) isWildChild = true;
        }
        
        public boolean match(ResolvedTypeX typeX) {
@@ -90,12 +92,27 @@ public class DeclareParents extends Declare {
                return ret;
        }
        
+       public boolean parentsIncludeInterface(World w) {
+               for (int i = 0; i < parents.size(); i++) {
+                       if (parents.get(i).getExactType().isInterface(w)) return true;
+               }
+         return false; 
+       }
+       public boolean parentsIncludeClass(World w) {
+               for (int i = 0; i < parents.size(); i++) {
+                       if (parents.get(i).getExactType().isClass(w)) return true;
+               }
+         return false; 
+       }
+       
     public void resolve(IScope scope) {
        child = child.resolveBindings(scope, Bindings.NONE, false, false);
        parents = parents.resolveBindings(scope, Bindings.NONE, false, true); 
-//     for (int i=0; i < parents.size(); i++) {
-//             parents.get(i).assertExactType(scope.getMessageHandler());
-//             }
+
+//      Could assert this ...
+//             for (int i=0; i < parents.size(); i++) {
+//                     parents.get(i).assertExactType(scope.getMessageHandler());
+//                     }
     }
 
        public TypePatternList getParents() {
@@ -110,7 +127,7 @@ public class DeclareParents extends Declare {
                return false;
        }
        
-       private ResolvedTypeX maybeGetNewParent(ResolvedTypeX targetType, TypePattern typePattern, World world) {
+       private ResolvedTypeX maybeGetNewParent(ResolvedTypeX targetType, TypePattern typePattern, World world,boolean reportErrors) {
                if (typePattern == TypePattern.NO) return null;  // already had an error here
                TypeX iType = typePattern.getExactType();
                ResolvedTypeX parentType = iType.resolve(world);
@@ -121,8 +138,64 @@ public class DeclareParents extends Declare {
                                this.getSourceLocation(), null);
                        return null;
                }
-                       
+
                if (parentType.isAssignableFrom(targetType)) return null;  // already a parent
+               
+               // Enum types that are targetted for decp through a wild type pattern get linted 
+               if (reportErrors && isWildChild && targetType.isEnum()) {
+                       world.getLint().enumAsTargetForDecpIgnored.signal(targetType.toString(),getSourceLocation());   
+               }
+               
+               // Annotation types that are targetted for decp through a wild type pattern get linted 
+               if (reportErrors && isWildChild && targetType.isAnnotation()) {
+                       world.getLint().annotationAsTargetForDecpIgnored.signal(targetType.toString(),getSourceLocation());     
+               }
+
+               // 1. Can't use decp to make an enum/annotation type implement an interface
+               if (targetType.isEnum() && parentType.isInterface()) {
+                       if (reportErrors && !isWildChild)  {
+                               world.showMessage(IMessage.ERROR,
+                                               WeaverMessages.format(WeaverMessages.CANT_DECP_ON_ENUM_TO_IMPL_INTERFACE,targetType),getSourceLocation(),null);
+                       }
+                       return null;
+               }
+               if (targetType.isAnnotation() && parentType.isInterface()) {
+                       if (reportErrors && !isWildChild)  {
+                               world.showMessage(IMessage.ERROR,WeaverMessages.format(WeaverMessages.CANT_DECP_ON_ANNOTATION_TO_IMPL_INTERFACE,targetType),getSourceLocation(),null);
+                       }
+                       return null;
+               }
+               
+               // 2. Can't use decp to change supertype of an enum/annotation
+               if (targetType.isEnum() && parentType.isClass()) {
+                       if (reportErrors && !isWildChild) {
+                               world.showMessage(IMessage.ERROR,WeaverMessages.format(WeaverMessages.CANT_DECP_ON_ENUM_TO_EXTEND_CLASS,targetType),getSourceLocation(),null);
+                       }
+                       return null;
+               }
+               if (targetType.isAnnotation() && parentType.isClass()) {
+                       if (reportErrors && !isWildChild) {
+                               world.showMessage(IMessage.ERROR,WeaverMessages.format(WeaverMessages.CANT_DECP_ON_ANNOTATION_TO_EXTEND_CLASS,targetType),getSourceLocation(),null);
+                       }
+                       return null;
+               }
+               
+               // 3. Can't use decp to declare java.lang.Enum/java.lang.annotation.Annotation as the parent of a type
+               if (parentType.getSignature().equals(TypeX.ENUM.getSignature())) {
+                       if (reportErrors && !isWildChild) {
+                           world.showMessage(IMessage.ERROR,
+                                       WeaverMessages.format(WeaverMessages.CANT_DECP_TO_MAKE_ENUM_SUPERTYPE,targetType),getSourceLocation(),null);
+                       }
+                       return null;
+               }       
+               if (parentType.getSignature().equals(TypeX.ANNOTATION.getSignature())) {
+                       if (reportErrors && !isWildChild) {
+                           world.showMessage(IMessage.ERROR,
+                                       WeaverMessages.format(WeaverMessages.CANT_DECP_TO_MAKE_ANNOTATION_SUPERTYPE,targetType),getSourceLocation(),null);
+                       }
+                       return null;
+               }       
+                       
                                        
                if (targetType.isAssignableFrom(parentType)) {
                        world.showMessage(IMessage.ERROR,
@@ -159,12 +232,12 @@ public class DeclareParents extends Declare {
        }
        
 
-       public List/*<ResolvedTypeX>*/ findMatchingNewParents(ResolvedTypeX onType) {
+       public List/*<ResolvedTypeX>*/ findMatchingNewParents(ResolvedTypeX onType,boolean reportErrors) {
                if (!match(onType)) return Collections.EMPTY_LIST;
                
                List ret = new ArrayList();
                for (int i=0; i < parents.size(); i++) {
-                       ResolvedTypeX t = maybeGetNewParent(onType, parents.get(i), onType.getWorld());
+                       ResolvedTypeX t = maybeGetNewParent(onType, parents.get(i), onType.getWorld(),reportErrors);
                        if (t != null) ret.add(t);
                }