Coverage Report - com.puppycrawl.tools.checkstyle.checks.coding.PackageDeclarationCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
PackageDeclarationCheck
100%
27/27
100%
8/8
1.5
 
 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.checks.coding;
 21  
 
 22  
 import java.io.File;
 23  
 
 24  
 import com.puppycrawl.tools.checkstyle.FileStatefulCheck;
 25  
 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
 26  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 27  
 import com.puppycrawl.tools.checkstyle.api.FullIdent;
 28  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 29  
 
 30  
 /**
 31  
  * Ensures there is a package declaration.
 32  
  * Optionally checks if directory structure matches package name.
 33  
  * Rationale: Classes that live in the null package cannot be
 34  
  * imported. Many novice developers are not aware of this.
 35  
  * Packages provide logical namespace to classes and should be stored in
 36  
  * the form of directory levels to provide physical grouping to your classes.
 37  
  * These directories are added to the classpath so that your classes
 38  
  * are visible to JVM when it runs the code.
 39  
  *
 40  
  * @author <a href="mailto:simon@redhillconsulting.com.au">Simon Harris</a>
 41  
  * @author Oliver Burn
 42  
  * @author Vikramaditya Kukreja
 43  
  */
 44  
 @FileStatefulCheck
 45  18
 public final class PackageDeclarationCheck extends AbstractCheck {
 46  
 
 47  
     /**
 48  
      * A key is pointing to the warning message text in "messages.properties"
 49  
      * file.
 50  
      */
 51  
     public static final String MSG_KEY_MISSING = "missing.package.declaration";
 52  
 
 53  
     /**
 54  
      * A key is pointing to the warning message text in "messages.properties"
 55  
      * file.
 56  
      */
 57  
     public static final String MSG_KEY_MISMATCH = "mismatch.package.directory";
 58  
 
 59  
     /** Line number used to log violation when no AST nodes are present in file. */
 60  
     private static final int DEFAULT_LINE_NUMBER = 1;
 61  
 
 62  
     /** Is package defined. */
 63  
     private boolean defined;
 64  
 
 65  
     /** Whether to check for directory and package name match. */
 66  18
     private boolean matchDirectoryStructure = true;
 67  
 
 68  
     /**
 69  
      * Set whether to check for directory and package name match.
 70  
      * @param matchDirectoryStructure the new value.
 71  
      */
 72  
     public void setMatchDirectoryStructure(boolean matchDirectoryStructure) {
 73  4
         this.matchDirectoryStructure = matchDirectoryStructure;
 74  4
     }
 75  
 
 76  
     @Override
 77  
     public int[] getDefaultTokens() {
 78  29
         return getRequiredTokens();
 79  
     }
 80  
 
 81  
     @Override
 82  
     public int[] getRequiredTokens() {
 83  63
         return new int[] {TokenTypes.PACKAGE_DEF};
 84  
     }
 85  
 
 86  
     @Override
 87  
     public int[] getAcceptableTokens() {
 88  5
         return getRequiredTokens();
 89  
     }
 90  
 
 91  
     @Override
 92  
     public void beginTree(DetailAST ast) {
 93  10
         defined = false;
 94  10
     }
 95  
 
 96  
     @Override
 97  
     public void finishTree(DetailAST ast) {
 98  10
         if (!defined) {
 99  2
             int lineNumber = DEFAULT_LINE_NUMBER;
 100  2
             if (ast != null) {
 101  1
                 lineNumber = ast.getLineNo();
 102  
             }
 103  2
             log(lineNumber, MSG_KEY_MISSING);
 104  
         }
 105  10
     }
 106  
 
 107  
     @Override
 108  
     public void visitToken(DetailAST ast) {
 109  8
         defined = true;
 110  
 
 111  8
         if (matchDirectoryStructure) {
 112  
 
 113  5
             final DetailAST packageNameAst = ast.getLastChild().getPreviousSibling();
 114  5
             final FullIdent fullIdent = FullIdent.createFullIdent(packageNameAst);
 115  5
             final String packageName = fullIdent.getText().replace('.', File.separatorChar);
 116  
 
 117  5
             final String directoryName = getDirectoryName();
 118  
 
 119  5
             if (!directoryName.endsWith(packageName)) {
 120  3
                 log(fullIdent.getLineNo(), MSG_KEY_MISMATCH, packageName);
 121  
             }
 122  
         }
 123  8
     }
 124  
 
 125  
     /**
 126  
      * Returns the directory name this file is in.
 127  
      * @return Directory name.
 128  
      */
 129  
     private String getDirectoryName() {
 130  5
         final String fileName = getFileContents().getFileName();
 131  5
         final int lastSeparatorPos = fileName.lastIndexOf(File.separatorChar);
 132  5
         return fileName.substring(0, lastSeparatorPos);
 133  
     }
 134  
 }