Coverage Report - com.puppycrawl.tools.checkstyle.checks.header.RegexpHeaderCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
RegexpHeaderCheck
93%
40/43
87%
28/32
4.4
 
 1  
 ////////////////////////////////////////////////////////////////////////////////
 2  
 // checkstyle: Checks Java source code for adherence to a set of rules.
 3  
 // Copyright (C) 2001-2014  Oliver Burn
 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.checks.header;
 21  
 
 22  
 import java.util.Arrays;
 23  
 
 24  
 import java.io.File;
 25  
 import java.util.List;
 26  
 import java.util.regex.Pattern;
 27  
 import java.util.regex.PatternSyntaxException;
 28  
 
 29  
 import org.apache.commons.beanutils.ConversionException;
 30  
 
 31  
 import com.google.common.collect.Lists;
 32  
 import com.puppycrawl.tools.checkstyle.api.Utils;
 33  
 
 34  
 /**
 35  
  * Checks the header of the source against a header file that contains a
 36  
  * {@link java.util.regex.Pattern regular expression}
 37  
  * for each line of the source header.
 38  
  *
 39  
  * @author Lars Kühne
 40  
  * @author o_sukhodolsky
 41  
  */
 42  11
 public class RegexpHeaderCheck extends AbstractHeaderCheck
 43  
 {
 44  
     /** empty array to avoid instantiations. */
 45  1
     private static final int[] EMPTY_INT_ARRAY = new int[0];
 46  
 
 47  
     /** the compiled regular expressions */
 48  11
     private final List<Pattern> mHeaderRegexps = Lists.newArrayList();
 49  
 
 50  
     /** the header lines to repeat (0 or more) in the check, sorted. */
 51  11
     private int[] mMultiLines = EMPTY_INT_ARRAY;
 52  
 
 53  
     /**
 54  
      * Set the lines numbers to repeat in the header check.
 55  
      * @param aList comma separated list of line numbers to repeat in header.
 56  
      */
 57  
     public void setMultiLines(int[] aList)
 58  
     {
 59  6
         if ((aList == null) || (aList.length == 0)) {
 60  0
             mMultiLines = EMPTY_INT_ARRAY;
 61  0
             return;
 62  
         }
 63  
 
 64  6
         mMultiLines = new int[aList.length];
 65  6
         System.arraycopy(aList, 0, mMultiLines, 0, aList.length);
 66  6
         Arrays.sort(mMultiLines);
 67  6
     }
 68  
 
 69  
     @Override
 70  
     protected void processFiltered(File aFile, List<String> aLines)
 71  
     {
 72  10
         final int headerSize = getHeaderLines().size();
 73  10
         final int fileSize = aLines.size();
 74  
 
 75  10
         if (headerSize - mMultiLines.length > fileSize) {
 76  0
             log(1, "header.missing");
 77  
         }
 78  
         else {
 79  10
             int headerLineNo = 0;
 80  
             int i;
 81  63
             for (i = 0; (headerLineNo < headerSize) && (i < fileSize); i++) {
 82  56
                 final String line = aLines.get(i);
 83  56
                 boolean isMatch = isMatch(line, headerLineNo);
 84  68
                 while (!isMatch && isMultiLine(headerLineNo)) {
 85  12
                     headerLineNo++;
 86  12
                     isMatch = (headerLineNo == headerSize)
 87  
                             || isMatch(line, headerLineNo);
 88  
                 }
 89  56
                 if (!isMatch) {
 90  3
                     log(i + 1, "header.mismatch", getHeaderLines().get(
 91  
                             headerLineNo));
 92  3
                     break; // stop checking
 93  
                 }
 94  53
                 if (!isMultiLine(headerLineNo)) {
 95  38
                     headerLineNo++;
 96  
                 }
 97  
             }
 98  10
             if (i == fileSize) {
 99  
                 // if file finished, but we have at least one non-multi-line
 100  
                 // header isn't completed
 101  3
                 for (; headerLineNo < headerSize; headerLineNo++) {
 102  2
                     if (!isMultiLine(headerLineNo)) {
 103  1
                         log(1, "header.missing");
 104  1
                         break;
 105  
                     }
 106  
                 }
 107  
             }
 108  
         }
 109  10
     }
 110  
 
 111  
     /**
 112  
      * Checks if a code line matches the required header line.
 113  
      * @param aLine the code line
 114  
      * @param aHeaderLineNo the header line number.
 115  
      * @return true if and only if the line matches the required header line.
 116  
      */
 117  
     private boolean isMatch(String aLine, int aHeaderLineNo)
 118  
     {
 119  66
         return mHeaderRegexps.get(aHeaderLineNo).matcher(aLine).find();
 120  
     }
 121  
 
 122  
     /**
 123  
      * @param aLineNo a line number
 124  
      * @return if <code>aLineNo</code> is one of the repeat header lines.
 125  
      */
 126  
     private boolean isMultiLine(int aLineNo)
 127  
     {
 128  70
         return (Arrays.binarySearch(mMultiLines, aLineNo + 1) >= 0);
 129  
     }
 130  
 
 131  
     @Override
 132  
     protected void postprocessHeaderLines()
 133  
     {
 134  11
         final List<String> headerLines = getHeaderLines();
 135  11
         mHeaderRegexps.clear();
 136  11
         for (String line : headerLines) {
 137  
             try {
 138  
                 // TODO: Not sure if cache in Utils is still necessary
 139  63
                 mHeaderRegexps.add(Utils.getPattern(line));
 140  
             }
 141  1
             catch (final PatternSyntaxException ex) {
 142  1
                 throw new ConversionException("line "
 143  
                         + (mHeaderRegexps.size() + 1)
 144  
                         + " in header specification"
 145  
                         + " is not a regular expression");
 146  62
             }
 147  
         }
 148  10
     }
 149  
 
 150  
 }