Coverage Report - com.puppycrawl.tools.checkstyle.utils.ModuleReflectionUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
ModuleReflectionUtils
100%
32/32
100%
26/26
0
 
 1  
 ////////////////////////////////////////////////////////////////////////////////
 2  
 // checkstyle: Checks Java source code for adherence to a set of rules.
 3  
 // Copyright (C) 2001-2017 the original author or authors.
 4  
 //
 5  
 // This library is free software; you can redistribute it and/or
 6  
 // modify it under the terms of the GNU Lesser General Public
 7  
 // License as published by the Free Software Foundation; either
 8  
 // version 2.1 of the License, or (at your option) any later version.
 9  
 //
 10  
 // This library is distributed in the hope that it will be useful,
 11  
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
 // Lesser General Public License for more details.
 14  
 //
 15  
 // You should have received a copy of the GNU Lesser General Public
 16  
 // License along with this library; if not, write to the Free Software
 17  
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 18  
 ////////////////////////////////////////////////////////////////////////////////
 19  
 
 20  
 package com.puppycrawl.tools.checkstyle.utils;
 21  
 
 22  
 import java.io.IOException;
 23  
 import java.lang.reflect.Constructor;
 24  
 import java.lang.reflect.Modifier;
 25  
 import java.util.Collection;
 26  
 import java.util.Set;
 27  
 import java.util.stream.Collectors;
 28  
 
 29  
 import com.google.common.reflect.ClassPath;
 30  
 import com.puppycrawl.tools.checkstyle.TreeWalkerFilter;
 31  
 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
 32  
 import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
 33  
 import com.puppycrawl.tools.checkstyle.api.AuditListener;
 34  
 import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
 35  
 import com.puppycrawl.tools.checkstyle.api.BeforeExecutionFileFilter;
 36  
 import com.puppycrawl.tools.checkstyle.api.Filter;
 37  
 import com.puppycrawl.tools.checkstyle.api.RootModule;
 38  
 
 39  
 /**
 40  
  * Contains utility methods for module reflection.
 41  
  * @author LuoLiangchen
 42  
  */
 43  
 public final class ModuleReflectionUtils {
 44  
 
 45  
     /** Prevent instantiation. */
 46  1
     private ModuleReflectionUtils() {
 47  1
     }
 48  
 
 49  
     /**
 50  
      * Gets checkstyle's modules (directly, not recursively) in the given packages.
 51  
      * @param packages the collection of package names to use
 52  
      * @param loader the class loader used to load Checkstyle package names
 53  
      * @return the set of checkstyle's module classes
 54  
      * @throws IOException if the attempt to read class path resources failed
 55  
      * @see #isCheckstyleModule(Class)
 56  
      */
 57  
     public static Set<Class<?>> getCheckstyleModules(
 58  
             Collection<String> packages, ClassLoader loader) throws IOException {
 59  9
         final ClassPath classPath = ClassPath.from(loader);
 60  16
         return packages.stream()
 61  17
                 .flatMap(pkg -> classPath.getTopLevelClasses(pkg).stream())
 62  8
                 .map(ClassPath.ClassInfo::load)
 63  8
                 .filter(ModuleReflectionUtils::isCheckstyleModule)
 64  8
                 .collect(Collectors.toSet());
 65  
     }
 66  
 
 67  
     /**
 68  
      * Checks whether a class may be considered as a checkstyle module. Checkstyle's modules are
 69  
      * non-abstract classes, which are either checkstyle's checks, file sets, filters, file filters,
 70  
      * {@code TreeWalker} filters, audit listener, or root module.
 71  
      * @param clazz class to check.
 72  
      * @return true if the class may be considered as the checkstyle module.
 73  
      */
 74  
     public static boolean isCheckstyleModule(Class<?> clazz) {
 75  49920
         return isValidCheckstyleClass(clazz)
 76  2040
             && (isCheckstyleCheck(clazz)
 77  296
                     || isFileSetModule(clazz)
 78  138
                     || isFilterModule(clazz)
 79  101
                     || isFileFilterModule(clazz)
 80  88
                     || isTreeWalkerFilterModule(clazz)
 81  51
                     || isAuditListener(clazz)
 82  50
                     || isRootModule(clazz));
 83  
     }
 84  
 
 85  
     /**
 86  
      * Checks whether a class extends 'AutomaticBean', is non-abstract, and has a default
 87  
      * constructor.
 88  
      * @param clazz class to check.
 89  
      * @return true if a class may be considered a valid production class.
 90  
      */
 91  
     public static boolean isValidCheckstyleClass(Class<?> clazz) {
 92  49928
         return AutomaticBean.class.isAssignableFrom(clazz)
 93  2225
                 && !Modifier.isAbstract(clazz.getModifiers())
 94  2080
                 && hasDefaultConstructor(clazz);
 95  
     }
 96  
 
 97  
     /**
 98  
      * Checks if the class has a default constructor.
 99  
      * @param clazz class to check
 100  
      * @return true if the class has a default constructor.
 101  
      */
 102  
     private static boolean hasDefaultConstructor(Class<?> clazz) {
 103  2080
         boolean result = false;
 104  2197
         for (Constructor<?> constructor : clazz.getDeclaredConstructors()) {
 105  2158
             if (constructor.getParameterCount() == 0) {
 106  2041
                 result = true;
 107  2041
                 break;
 108  
             }
 109  
         }
 110  2080
         return result;
 111  
     }
 112  
 
 113  
     /**
 114  
      * Checks whether a class may be considered as the checkstyle check.
 115  
      * Checkstyle's checks are classes which implement 'AbstractCheck' interface.
 116  
      * @param clazz class to check.
 117  
      * @return true if a class may be considered as the checkstyle check.
 118  
      */
 119  
     public static boolean isCheckstyleCheck(Class<?> clazz) {
 120  4353
         return AbstractCheck.class.isAssignableFrom(clazz);
 121  
     }
 122  
 
 123  
     /**
 124  
      * Checks whether a class may be considered as the checkstyle file set.
 125  
      * Checkstyle's file sets are classes which implement 'AbstractFileSetCheck' interface.
 126  
      * @param clazz class to check.
 127  
      * @return true if a class may be considered as the checkstyle file set.
 128  
      */
 129  
     public static boolean isFileSetModule(Class<?> clazz) {
 130  298
         return AbstractFileSetCheck.class.isAssignableFrom(clazz);
 131  
     }
 132  
 
 133  
     /**
 134  
      * Checks whether a class may be considered as the checkstyle filter.
 135  
      * Checkstyle's filters are classes which implement 'Filter' interface.
 136  
      * @param clazz class to check.
 137  
      * @return true if a class may be considered as the checkstyle filter.
 138  
      */
 139  
     public static boolean isFilterModule(Class<?> clazz) {
 140  140
         return Filter.class.isAssignableFrom(clazz);
 141  
     }
 142  
 
 143  
     /**
 144  
      * Checks whether a class may be considered as the checkstyle file filter.
 145  
      * Checkstyle's file filters are classes which implement 'BeforeExecutionFileFilter' interface.
 146  
      * @param clazz class to check.
 147  
      * @return true if a class may be considered as the checkstyle file filter.
 148  
      */
 149  
     public static boolean isFileFilterModule(Class<?> clazz) {
 150  103
         return BeforeExecutionFileFilter.class.isAssignableFrom(clazz);
 151  
     }
 152  
 
 153  
     /**
 154  
      * Checks whether a class may be considered as the checkstyle audit listener module.
 155  
      * Checkstyle's audit listener modules are classes which implement 'AuditListener' interface.
 156  
      * @param clazz class to check.
 157  
      * @return true if a class may be considered as the checkstyle audit listener module.
 158  
      */
 159  
     public static boolean isAuditListener(Class<?> clazz) {
 160  53
         return AuditListener.class.isAssignableFrom(clazz);
 161  
     }
 162  
 
 163  
     /**
 164  
      * Checks whether a class may be considered as the checkstyle root module.
 165  
      * Checkstyle's root modules are classes which implement 'RootModule' interface.
 166  
      * @param clazz class to check.
 167  
      * @return true if a class may be considered as the checkstyle root module.
 168  
      */
 169  
     public static boolean isRootModule(Class<?> clazz) {
 170  215
         return RootModule.class.isAssignableFrom(clazz);
 171  
     }
 172  
 
 173  
     /**
 174  
      * Checks whether a class may be considered as the checkstyle {@code TreeWalker} filter.
 175  
      * Checkstyle's {@code TreeWalker} filters are classes which implement 'TreeWalkerFilter'
 176  
      * interface.
 177  
      * @param clazz class to check.
 178  
      * @return true if a class may be considered as the checkstyle {@code TreeWalker} filter.
 179  
      */
 180  
     public static boolean isTreeWalkerFilterModule(Class<?> clazz) {
 181  239
         return TreeWalkerFilter.class.isAssignableFrom(clazz);
 182  
     }
 183  
 }