View Javadoc

    1   /***
    2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    3    */
    4   package net.sourceforge.pmd.symboltable;
    5
    6   import java.util.ArrayList;
    7   import java.util.HashMap;
    8   import java.util.HashSet;
    9   import java.util.Iterator;
    10  import java.util.List;
    11  import java.util.Map;
    12  import java.util.Set;
    13
    14  /***
    15   * Keeps track of the types encountered in a ASTCompilationUnit
    16   */
    17  public class TypeSet {
    18
    19
    20      /***
    21       * TODO should Resolver provide a canResolve() and a resolve()?
    22       * Requiring 2 calls seems clunky... but so does this
    23       * throwing an exception for flow control...
    24       */
    25      public interface Resolver {
    26          Class resolve(String name) throws ClassNotFoundException;
    27      }
    28
    29      public static class ExplicitImportResolver implements Resolver {
    30          private Set importStmts;
    31
    32          public ExplicitImportResolver(Set importStmts) {
    33              this.importStmts = importStmts;
    34          }
    35
    36          public Class resolve(String name) throws ClassNotFoundException {
    37              for (Iterator i = importStmts.iterator(); i.hasNext();) {
    38                  String importStmt = (String) i.next();
    39                  if (importStmt.endsWith(name)) {
    40                      return Class.forName(importStmt);
    41                  }
    42              }
    43              throw new ClassNotFoundException("Type " + name + " not found");
    44          }
    45      }
    46
    47      public static class CurrentPackageResolver implements Resolver {
    48          private String pkg;
    49
    50          public CurrentPackageResolver(String pkg) {
    51              this.pkg = pkg;
    52          }
    53
    54          public Class resolve(String name) throws ClassNotFoundException {
    55              return Class.forName(pkg + name);
    56          }
    57      }
    58
    59      // TODO cite the JLS section on implicit imports
    60      public static class ImplicitImportResolver implements Resolver {
    61          public Class resolve(String name) throws ClassNotFoundException {
    62              return Class.forName("java.lang." + name);
    63          }
    64      }
    65
    66      public static class ImportOnDemandResolver implements Resolver {
    67          private Set importStmts;
    68
    69          public ImportOnDemandResolver(Set importStmts) {
    70              this.importStmts = importStmts;
    71          }
    72
    73          public Class resolve(String name) throws ClassNotFoundException {
    74              for (Iterator i = importStmts.iterator(); i.hasNext();) {
    75                  String importStmt = (String) i.next();
    76                  if (importStmt.endsWith("*")) {
    77                      try {
    78                          String importPkg = importStmt.substring(0, importStmt.indexOf("*") - 1);
    79                          return Class.forName(importPkg + "." + name);
    80                      } catch (ClassNotFoundException cnfe) {
    81                      }
    82                  }
    83              }
    84              throw new ClassNotFoundException("Type " + name + " not found");
    85          }
    86      }
    87
    88      public static class PrimitiveTypeResolver implements Resolver {
    89          private Map primitiveTypes = new HashMap();
    90
    91          public PrimitiveTypeResolver() {
    92              primitiveTypes.put("int", int.class);
    93              primitiveTypes.put("float", float.class);
    94              primitiveTypes.put("double", double.class);
    95              primitiveTypes.put("long", long.class);
    96              primitiveTypes.put("boolean", boolean.class);
    97              primitiveTypes.put("byte", byte.class);
    98              primitiveTypes.put("short", short.class);
    99              primitiveTypes.put("char", char.class);
    100         }
    101
    102         public Class resolve(String name) throws ClassNotFoundException {
    103             if (!primitiveTypes.containsKey(name)) {
    104                 throw new ClassNotFoundException();
    105             }
    106             return (Class) primitiveTypes.get(name);
    107         }
    108     }
    109
    110     public static class VoidResolver implements Resolver {
    111         public Class resolve(String name) throws ClassNotFoundException {
    112             if (name.equals("void")) {
    113                 return void.class;
    114             }
    115             throw new ClassNotFoundException();
    116         }
    117     }
    118
    119     public static class FullyQualifiedNameResolver implements Resolver {
    120         public Class resolve(String name) throws ClassNotFoundException {
    121             return Class.forName(name);
    122         }
    123     }
    124
    125     private String pkg;
    126     private Set imports = new HashSet();
    127     private List resolvers = new ArrayList();
    128
    129     public void setASTCompilationUnitPackage(String pkg) {
    130         this.pkg = pkg;
    131     }
    132
    133     public String getASTCompilationUnitPackage() {
    134         return pkg;
    135     }
    136
    137     public void addImport(String importString) {
    138         imports.add(importString);
    139     }
    140
    141     public int getImportsCount() {
    142         return imports.size();
    143     }
    144
    145     public Class findClass(String name) throws ClassNotFoundException {
    146         // we don't build the resolvers until now since we first want to get all the imports
    147         if (resolvers.isEmpty()) {
    148             buildResolvers();
    149         }
    150
    151         for (Iterator i = resolvers.iterator(); i.hasNext();) {
    152             Resolver resolver = (Resolver) i.next();
    153             try {
    154                 return resolver.resolve(name);
    155             } catch (ClassNotFoundException cnfe) {
    156             }
    157         }
    158
    159         throw new ClassNotFoundException("Type " + name + " not found");
    160     }
    161
    162     private void buildResolvers() {
    163         resolvers.add(new PrimitiveTypeResolver());
    164         resolvers.add(new VoidResolver());
    165         resolvers.add(new ExplicitImportResolver(imports));
    166         resolvers.add(new CurrentPackageResolver(pkg));
    167         resolvers.add(new ImplicitImportResolver());
    168         resolvers.add(new ImportOnDemandResolver(imports));
    169         resolvers.add(new FullyQualifiedNameResolver());
    170     }
    171
    172 }