001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2014 Oliver Burn 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018//////////////////////////////////////////////////////////////////////////////// 019package com.puppycrawl.tools.checkstyle.checks.javadoc; 020 021import com.puppycrawl.tools.checkstyle.api.Check; 022import com.puppycrawl.tools.checkstyle.api.DetailAST; 023import com.puppycrawl.tools.checkstyle.api.FileContents; 024import com.puppycrawl.tools.checkstyle.api.Scope; 025import com.puppycrawl.tools.checkstyle.api.ScopeUtils; 026import com.puppycrawl.tools.checkstyle.api.TextBlock; 027import com.puppycrawl.tools.checkstyle.api.TokenTypes; 028 029import java.util.regex.Pattern; 030 031/** 032 * Checks that a variable has Javadoc comment. 033 * 034 * @author Oliver Burn 035 * @version 1.0 036 */ 037public class JavadocVariableCheck 038 extends Check 039{ 040 /** the scope to check */ 041 private Scope scope = Scope.PRIVATE; 042 043 /** the visibility scope where Javadoc comments shouldn't be checked **/ 044 private Scope excludeScope; 045 046 /** the regular expression to ignore variable name */ 047 private String ignoreNameRegexp; 048 049 /** the pattern to ignore variable name */ 050 private Pattern ignoreNamePattern; 051 052 /** 053 * Sets the scope to check. 054 * @param from string to get the scope from 055 */ 056 public void setScope(String from) 057 { 058 scope = Scope.getInstance(from); 059 } 060 061 /** 062 * Set the excludeScope. 063 * @param scope a <code>String</code> value 064 */ 065 public void setExcludeScope(String scope) 066 { 067 excludeScope = Scope.getInstance(scope); 068 } 069 070 /** 071 * Sets the variable names to ignore in the check. 072 * @param regexp regexp to define variable names to ignore. 073 */ 074 public void setIgnoreNamePattern(String regexp) 075 { 076 ignoreNameRegexp = regexp; 077 if (!(regexp == null || regexp.length() == 0)) { 078 ignoreNamePattern = Pattern.compile(regexp); 079 } 080 else { 081 ignoreNamePattern = null; 082 } 083 } 084 085 /** 086 * Gets the variable names to ignore in the check. 087 * @return true regexp string to define variable names to ignore. 088 */ 089 public String getIgnoreNamePattern() 090 { 091 return ignoreNameRegexp; 092 } 093 094 @Override 095 public int[] getDefaultTokens() 096 { 097 return new int[] { 098 TokenTypes.VARIABLE_DEF, 099 TokenTypes.ENUM_CONSTANT_DEF, 100 }; 101 } 102 103 @Override 104 public void visitToken(DetailAST ast) 105 { 106 if (shouldCheck(ast)) { 107 final FileContents contents = getFileContents(); 108 final TextBlock cmt = 109 contents.getJavadocBefore(ast.getLineNo()); 110 111 if (cmt == null) { 112 log(ast, "javadoc.missing"); 113 } 114 } 115 } 116 117 /** 118 * Decides whether the variable name of an AST is in the ignore list. 119 * @param ast the AST to check 120 * @return true if the variable name of ast is in the ignore list. 121 */ 122 private boolean isIgnored(DetailAST ast) 123 { 124 final String name = ast.findFirstToken(TokenTypes.IDENT).getText(); 125 return ignoreNamePattern != null 126 && ignoreNamePattern.matcher(name).matches(); 127 } 128 129 /** 130 * Whether we should check this node. 131 * @param ast a given node. 132 * @return whether we should check a given node. 133 */ 134 private boolean shouldCheck(final DetailAST ast) 135 { 136 if (ScopeUtils.inCodeBlock(ast) || isIgnored(ast)) { 137 return false; 138 } 139 140 final Scope scope; 141 if (ast.getType() == TokenTypes.ENUM_CONSTANT_DEF) { 142 scope = Scope.PUBLIC; 143 } 144 else { 145 final DetailAST mods = ast.findFirstToken(TokenTypes.MODIFIERS); 146 final Scope declaredScope = ScopeUtils.getScopeFromMods(mods); 147 scope = 148 ScopeUtils.inInterfaceOrAnnotationBlock(ast) 149 ? Scope.PUBLIC : declaredScope; 150 } 151 152 final Scope surroundingScope = ScopeUtils.getSurroundingScope(ast); 153 154 return scope.isIn(this.scope) && surroundingScope.isIn(this.scope) 155 && ((excludeScope == null) 156 || !scope.isIn(excludeScope) 157 || !surroundingScope.isIn(excludeScope)); 158 } 159}