Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2003-2007 the original author or authors.
   *
   * Licensed 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.codehaus.groovy.control;
 
class used to verify correct usage of generics in class header (class and superclass declaration)

Author(s):
Jochen Theodorou
 
 public class GenericsVisitor extends ClassCodeVisitorSupport {
     private SourceUnit source;
     
     public GenericsVisitor(SourceUnit source) {
         this. = source;
     }
     
     protected SourceUnit getSourceUnit() {
         return ;
     }
     
     public void visitClass(ClassNode node) {
         boolean error=checkWildcard(node);
         if (errorreturn;
         checkGenericsUsage(node.getUnresolvedSuperClass(false), node.getSuperClass());
         ClassNode[] interfaces = node.getInterfaces();
         for (int i = 0; i < interfaces.lengthi++) {
             checkGenericsUsage(interfaces[i], interfaces[i].redirect());
         }
     }
     
     private boolean checkWildcard(ClassNode cn) {
         ClassNode sn = cn.getUnresolvedSuperClass(false);
         if (sn==nullreturn false;
         GenericsType[] generics = sn.getGenericsTypes();
         if (generics==nullreturn false;
         boolean error=false;
         for (int i = 0; i < generics.lengthi++) {
             if(generics[i].isWildcard()) {
                 addError("A supertype may not specifiy a wildcard type",sn);
                 error = true;
             }
         }
         return error;
     }
 
     private void checkGenericsUsage(ClassNode nClassNode cn) {
         GenericsType[] nTypes = n.getGenericsTypes();
         GenericsType[] cnTypes = cn.getGenericsTypes();
         // raw type usage is always allowed
         if (nTypes==nullreturn;
         // parameterize a type by using all of the parameters only
         if (cnTypes==null) {
             addError"The class "+n.getName()+" refers to the class "+
                       cn.getName()+" and uses "+nTypes.length+
                       " parameters, but the referred class takes no parameters"n);
             return;
         }
         if (nTypes.length!=cnTypes.length) {
             addError"The class "+n.getName()+" refers to the class "+
                       cn.getName()+" and uses "+nTypes.length+
                       " parameters, but the refered class needs "+
                       cnTypes.lengthn);
             return;
         }
         // check bounds
         for (int i=0; i<nTypes.lengthi++) {
             ClassNode nType = nTypes[i].getType();
             ClassNode cnType = cnTypes[i].getType();
             if (!nType.isDerivedFrom(cnType)) {
                 if (cnType.isInterface() && nType.declaresInterface(cnType)) continue;
                 addError("The type "+nTypes[i].getName()+
                          " is not a valid substitute for the bounded parameter <"+
                          getPrintName(cnTypes[i])+">",n);
             }
         }
     }
     
     private String getPrintName(GenericsType gt) {
         String ret = gt.getName();
         ClassNode[] upperBounds = gt.getUpperBounds();
         ClassNode lowerBound = gt.getLowerBound();
        if (upperBounds!=null) {
            ret += " extends ";
            for (int i = 0; i < upperBounds.lengthi++) {
                ret += getPrintName(upperBounds[i]);
                if (i+1<upperBounds.lengthret += " & ";
            }
        } else if (lowerBound!=null) {
            ret += " super "+getPrintName(lowerBound);
        }
        return ret;
    }
    
    private String getPrintName(ClassNode cn) {
        String ret = cn.getName();
        GenericsType[] gts = cn.getGenericsTypes();
        if (gts!=null) {
            ret += "<";
            for (int i = 0; i < gts.lengthi++) {
                if (i!=0) ret+=",";
                ret+=getPrintName(gts[i]);
            } 
            ret+=">";
        }
        return ret;
    }
    
    private void checkBounds(ClassNode[] givenClassNode[] restrictions) {
        if (restrictions==nullreturn;
        for (int i=0; i<given.lengthi++) {
            for (int j=0; j<restrictions.lengthj++) {
                if (! given[i].isDerivedFrom(restrictions[j])){}
            }
        }
    }
New to GrepCode? Check out our FAQ X