import eclipse 3.1 M4 compiler
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / ast / ASTNode.java
index 74ba90b..1457547 100644 (file)
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
@@ -26,14 +27,14 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
        public final static int Bit2 = 0x2;                                             // return type (operator) | name reference kind (name ref) | has local type (type, method, field decl)
        public final static int Bit3 = 0x4;                                             // return type (operator) | name reference kind (name ref) | implicit this (this ref)
        public final static int Bit4 = 0x8;                                             // return type (operator) | first assignment to local (local decl) | undocumented empty block (block, type and method decl)
-       public final static int Bit5 = 0x10;                                            // value for return (expression) | has all method bodies (unit)
+       public final static int Bit5 = 0x10;                                            // value for return (expression) | has all method bodies (unit) | supertype ref (type ref)
        public final static int Bit6 = 0x20;                                            // depth (name ref, msg) | only value required (binary expression) | ignore need cast check (cast expression)
        public final static int Bit7 = 0x40;                                            // depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression)
        public final static int Bit8 = 0x80;                                            // depth (name ref, msg) | operator (operator) 
        public final static int Bit9 = 0x100;                                   // depth (name ref, msg) | operator (operator) | is local type (type decl)
        public final static int Bit10= 0x200;                                   // depth (name ref, msg) | operator (operator) | is anonymous type (type decl)
        public final static int Bit11 = 0x400;                                  // depth (name ref, msg) | operator (operator) | is member type (type decl)
-       public final static int Bit12 = 0x800;                                  // depth (name ref, msg) | operator (operator)
+       public final static int Bit12 = 0x800;                                  // depth (name ref, msg) | operator (operator) | has abstract methods (type decl)
        public final static int Bit13 = 0x1000;                                 // depth (name ref, msg) 
        public final static int Bit14 = 0x2000;                                 // strictly assigned (reference lhs)
        public final static int Bit15 = 0x4000;                                 // is unnecessary cast (expression)
@@ -64,6 +65,22 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
        public final static long Bit38L = 0x2000000000L;
        public final static long Bit39L = 0x4000000000L;
        public final static long Bit40L = 0x8000000000L;
+       public final static long Bit41L = 0x10000000000L;
+       public final static long Bit42L = 0x20000000000L;
+       public final static long Bit43L = 0x40000000000L;
+       public final static long Bit44L = 0x80000000000L;
+       public final static long Bit45L = 0x100000000000L;
+       public final static long Bit46L = 0x200000000000L;
+       public final static long Bit47L = 0x400000000000L;
+       public final static long Bit48L = 0x800000000000L;
+       public final static long Bit49L = 0x1000000000000L;
+       public final static long Bit50L = 0x2000000000000L;
+       public final static long Bit51L = 0x4000000000000L;
+       public final static long Bit52L = 0x8000000000000L;
+       public final static long Bit53L = 0x10000000000000L;
+       public final static long Bit54L = 0x20000000000000L;
+       public final static long Bit55L = 0x40000000000000L;
+       public final static long Bit56L = 0x80000000000000L;
 
        public int bits = IsReachableMASK;                              // reachable by default
 
@@ -102,6 +119,7 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
        public static final int IsAnonymousTypeMASK = Bit10; // used to test for anonymous 
        public static final int AnonymousAndLocalMask = IsAnonymousTypeMASK | IsLocalTypeMASK; // used to set anonymous marker
        public static final int IsMemberTypeMASK = Bit11; // local member do not know it is local at parse time (need to look at binding)
+       public static final int HasAbstractMethods = Bit12; // used to promote abstract enums
        
        // for type, method and field declarations 
        public static final int HasLocalTypeMASK = Bit2; // cannot conflict with AddAssertionMASK
@@ -132,15 +150,80 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
        // for if statement
        public static final int IsElseIfStatement = Bit30;
        
+       // for type reference
+       public static final int IsSuperType = Bit5;
+       
+       // for variable argument
+       public static final int IsVarArgs = Bit15;
+       
        public ASTNode() {
 
                super();
        }
-
+       private static boolean checkInvocationArgument(BlockScope scope, Expression argument, TypeBinding parameterType, TypeBinding argumentType) {
+               argument.computeConversion(scope, parameterType, argumentType);
+
+               if (argumentType != NullBinding && parameterType.isWildcard() && ((WildcardBinding) parameterType).kind != Wildcard.SUPER)
+                   return true; // unsafeWildcardInvocation
+               if (argumentType != parameterType && argumentType.isRawType())
+               if (parameterType.isBoundParameterizedType() || parameterType.isGenericType())
+                               scope.problemReporter().unsafeRawConversion(argument, argumentType, parameterType);
+               return false;
+       }
+       public static void checkInvocationArguments(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding method, Expression[] arguments, TypeBinding[] argumentTypes, boolean argsContainCast, InvocationSite invocationSite) {
+               boolean unsafeWildcardInvocation = false;
+               TypeBinding[] params = method.parameters;
+               if (method.isVarargs()) {
+                       // 4 possibilities exist for a call to the vararg method foo(int i, long ... value) : foo(1), foo(1, 2), foo(1, 2, 3, 4) & foo(1, new long[] {1, 2})
+                       int lastIndex = params.length - 1;
+                       for (int i = 0; i < lastIndex; i++)
+                           if (checkInvocationArgument(scope, arguments[i], params[i], argumentTypes[i]))
+                                   unsafeWildcardInvocation = true;
+                  int argLength = arguments.length;
+                  if (lastIndex < argLength) { // vararg argument was provided
+                               TypeBinding parameterType = params[lastIndex];
+                           if (params.length != argLength || parameterType.dimensions() != argumentTypes[lastIndex].dimensions())
+                               parameterType = ((ArrayBinding) parameterType).elementsType(); // single element was provided for vararg parameter
+                               for (int i = lastIndex; i < argLength; i++)
+                                   if (checkInvocationArgument(scope, arguments[i], parameterType, argumentTypes[i]))
+                                           unsafeWildcardInvocation = true;
+                       }
+
+                  if (method.parameters.length == argumentTypes.length) { // 70056
+                               int varargIndex = method.parameters.length - 1;
+                               ArrayBinding varargType = (ArrayBinding) method.parameters[varargIndex];
+                               TypeBinding lastArgType = argumentTypes[varargIndex];
+                               if (lastArgType == NullBinding) {
+                                       if (!(varargType.leafComponentType().isBaseType() && varargType.dimensions() == 1))
+                                               scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite);
+                               } else if (varargType.dimensions <= lastArgType.dimensions()) {
+                                       int dimensions = lastArgType.dimensions();
+                                       if (lastArgType.leafComponentType().isBaseType())
+                                               dimensions--;
+                                       if (varargType.dimensions < dimensions)
+                                               scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite);
+                                       else if (varargType.dimensions == dimensions && varargType.leafComponentType != lastArgType.leafComponentType())
+                                               scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite);
+                               }
+                       }
+               } else {
+                       for (int i = 0, argLength = arguments.length; i < argLength; i++)
+                           if (checkInvocationArgument(scope, arguments[i], params[i], argumentTypes[i]))
+                                   unsafeWildcardInvocation = true;
+               }
+               if (argsContainCast) {
+                       CastExpression.checkNeedForArgumentCasts(scope, receiver, receiverType, method, arguments, argumentTypes, invocationSite);
+               }
+               if (unsafeWildcardInvocation) {
+                   scope.problemReporter().wildcardInvocation((ASTNode)invocationSite, receiverType, method, argumentTypes);
+               } else if (!receiverType.isUnboundWildcard() && method.declaringClass.isRawType() && method.hasSubstitutedParameters()) {
+                   scope.problemReporter().unsafeRawInvocation((ASTNode)invocationSite, method);
+               }
+       }
        public ASTNode concreteStatement() {
                return this;
        }
-
+       
        /* Answer true if the field use is considered deprecated.
        * An access in the same compilation unit is allowed.
        */
@@ -173,7 +256,7 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
 
                if (method.isPrivate() && !scope.isDefinedInMethod(method)) {
                        // ignore cases where method is used from within inside itself (e.g. direct recursions)
-                       method.modifiers |= AccPrivateUsed;
+                       method.original().modifiers |= AccPrivateUsed;
                }
                
                if (!method.isViewedAsDeprecated()) return false;
@@ -210,9 +293,15 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
 
                if (refType.isPrivate() && !scope.isDefinedInType(refType)) {
                        // ignore cases where type is used from within inside itself 
-                       refType.modifiers |= AccPrivateUsed;
+                       ((ReferenceBinding)refType.erasure()).modifiers |= AccPrivateUsed;
+               }
+               
+               if (refType.hasRestrictedAccess()) {
+                       AccessRestriction restriction = scope.environment().getAccessRestriction(type);
+                       if (restriction != null) {
+                               scope.problemReporter().forbiddenReference(type, this, restriction.getMessageTemplate());
+                       }
                }
-
                if (!refType.isViewedAsDeprecated()) return false;
                
                // inside same unit - no report
@@ -225,6 +314,15 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
 
        public abstract StringBuffer print(int indent, StringBuffer output);
 
+       public static StringBuffer printAnnotations(Annotation[] annotations, StringBuffer output) {
+               int length = annotations.length;
+               for (int i = 0; i < length; i++) {
+                       annotations[i].print(0, output);
+                       output.append(" "); //$NON-NLS-1$
+               }
+               return output;
+       }
+       
        public static StringBuffer printIndent(int indent, StringBuffer output) {
 
                for (int i = indent; i > 0; i--) output.append("  "); //$NON-NLS-1$
@@ -255,6 +353,68 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
                        output.append("abstract "); //$NON-NLS-1$
                return output;
        }
+       
+       /**
+        * Resolve annotations, and check duplicates, answers combined tagBits 
+        * for recognized standard annotations
+        */
+       public void resolveAnnotations(BlockScope scope, Annotation[] annotations, Binding recipient) {
+               if (recipient != null) {
+                       switch (recipient.kind()) {
+                               case Binding.PACKAGE :
+                                       // TODO (philippe) need support for package annotations
+                                       break;
+                               case Binding.TYPE :
+                               case Binding.GENERIC_TYPE :
+                               case Binding.TYPE_PARAMETER :
+                                       ReferenceBinding type = (ReferenceBinding) recipient;
+                                       if ((type.tagBits & TagBits.AnnotationResolved) != 0) return;
+                                       type.tagBits |= TagBits.AnnotationResolved;
+                                       break;
+                               case Binding.METHOD :
+                                       MethodBinding method = (MethodBinding) recipient;
+                                       if ((method.tagBits & TagBits.AnnotationResolved) != 0) return;
+                                       method.tagBits |= TagBits.AnnotationResolved;
+                                       break;
+                               case Binding.FIELD :
+                                       FieldBinding field = (FieldBinding) recipient;
+                                       if ((field.tagBits & TagBits.AnnotationResolved) != 0) return;
+                                       field.tagBits |= TagBits.AnnotationResolved;
+                                       break;
+                               case Binding.LOCAL :
+                                       LocalVariableBinding local = (LocalVariableBinding) recipient;
+                                       if ((local.tagBits & TagBits.AnnotationResolved) != 0) return;
+                                       local.tagBits |= TagBits.AnnotationResolved;
+                                       break;
+                       }                       
+               }
+               if (annotations == null) 
+                       return;
+               int length = annotations.length;
+               TypeBinding[] annotationTypes = new TypeBinding[length];
+               for (int i = 0; i < length; i++) {
+                       Annotation annotation = annotations[i];
+                       annotation.recipient = recipient;
+                       annotationTypes[i] = annotation.resolveType(scope);
+               }
+               // check duplicate annotations
+               for (int i = 0; i < length; i++) {
+                       TypeBinding annotationType = annotationTypes[i];
+                       if (annotationType == null) continue;
+                       boolean foundDuplicate = false;
+                       for (int j = i+1; j < length; j++) {
+                               if (annotationTypes[j] == annotationType) {
+                                       foundDuplicate = true;
+                                       annotationTypes[j] = null; // report it only once
+                                       scope.problemReporter().duplicateAnnotation(annotations[j]);
+                               }
+                       }
+                       if (foundDuplicate) {
+                               scope.problemReporter().duplicateAnnotation(annotations[i]);
+                       }
+               }
+       }
+       
        public int sourceStart() {
                return this.sourceStart;
        }