Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocTypeCheck.java


1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2003  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  package com.puppycrawl.tools.checkstyle.checks.javadoc;
20  
21  import org.apache.commons.beanutils.ConversionException;
22  import org.apache.regexp.RE;
23  import org.apache.regexp.RESyntaxException;
24  
25  import com.puppycrawl.tools.checkstyle.api.Check;
26  import com.puppycrawl.tools.checkstyle.api.DetailAST;
27  import com.puppycrawl.tools.checkstyle.api.FileContents;
28  import com.puppycrawl.tools.checkstyle.api.Scope;
29  import com.puppycrawl.tools.checkstyle.api.ScopeUtils;
30  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
31  import com.puppycrawl.tools.checkstyle.api.Utils;
32  
33  /**
34   * <p>
35   * Checks the Javadoc of a type.
36   * By default, does not check for author or version tags.
37   * The scope to verify is specified using the {@link Scope} class and
38   * defaults to {@link Scope#PRIVATE}. To verify another scope,
39   * set property scope to one of the {@link Scope} constants.
40   * To define the format for an author tag or a version tag,
41   * set property authorFormat or versionFormat respectively to a
42   * <a href="http://jakarta.apache.org/regexp/apidocs/org/apache/regexp/RE.html">
43   * regular expression</a>.
44   * </p>
45   * <p>
46   * An example of how to configure the check is:
47   * </p>
48   * <pre>
49   * &lt;module name="JavadocType"/&gt;
50   * </pre>
51   * <p> An example of how to configure the check for the
52   * {@link Scope#PUBLIC} scope is:
53   *</p>
54   * <pre>
55   * &lt;module name="JavadocType"&gt;
56   *    &lt;property name="scope" value="public"/&gt;
57   * &lt;/module&gt;
58   * </pre>
59   * <p> An example of how to configure the check for an author tag
60   *  and a version tag is:
61   *</p>
62   * <pre>
63   * &lt;module name="JavadocType"&gt;
64   *    &lt;property name="authorFormat" value="\S"/&gt;
65   *    &lt;property name="versionFormat" value="\S"/&gt;
66   * &lt;/module&gt;
67   * </pre>
68   * <p> An example of how to configure the check for a
69   * CVS revision version tag is:
70   *</p>
71   * <pre>
72   * &lt;module name="JavadocType"&gt;
73   *    &lt;property name="versionFormat" value="\$Revision.*\$"/&gt;
74   * &lt;/module&gt;
75   * </pre>
76   *
77  
78   * @author Oliver Burn
79   * @version 1.0
80   */
81  public class JavadocTypeCheck
82      extends Check
83  {
84      /** the scope to check for */
85      private Scope mScope = Scope.PRIVATE;
86      /** compiled regexp to match author tag **/
87      private RE mAuthorTagRE;
88      /** compiled regexp to match author tag content **/
89      private RE mAuthorFormatRE;
90      /** compiled regexp to match version tag **/
91      private RE mVersionTagRE;
92      /** compiled regexp to match version tag content **/
93      private RE mVersionFormatRE;
94      /** regexp to match author tag content */
95      private String mAuthorFormat;
96      /** regexp to match version tag content */
97      private String mVersionFormat;
98  
99      /**
100      * Sets the scope to check.
101      * @param aFrom string to set scope from
102      */
103     public void setScope(String aFrom)
104     {
105         mScope = Scope.getInstance(aFrom);
106     }
107 
108     /**
109      * Set the author tag pattern.
110      * @param aFormat a <code>String</code> value
111      * @throws ConversionException unable to parse aFormat
112      */
113     public void setAuthorFormat(String aFormat)
114         throws ConversionException
115     {
116         try {
117             mAuthorTagRE = Utils.getRE("@author\\s+(.*$)");
118             mAuthorFormat = aFormat;
119             mAuthorFormatRE = Utils.getRE(aFormat);
120         }
121         catch (RESyntaxException e) {
122             throw new ConversionException("unable to parse " + aFormat, e);
123         }
124     }
125 
126     /**
127      * Set the version format pattern.
128      * @param aFormat a <code>String</code> value
129      * @throws ConversionException unable to parse aFormat
130      */
131     public void setVersionFormat(String aFormat)
132         throws ConversionException
133     {
134         try {
135             mVersionTagRE = Utils.getRE("@version\\s+(.*$)");
136             mVersionFormat = aFormat;
137             mVersionFormatRE = Utils.getRE(aFormat);
138         }
139         catch (RESyntaxException e) {
140             throw new ConversionException("unable to parse " + aFormat, e);
141         }
142 
143     }
144 
145     /** @see com.puppycrawl.tools.checkstyle.api.Check */
146     public int[] getDefaultTokens()
147     {
148         return new int[] {TokenTypes.INTERFACE_DEF, TokenTypes.CLASS_DEF};
149     }
150 
151     /** @see com.puppycrawl.tools.checkstyle.api.Check */
152     public void visitToken(DetailAST aAST)
153     {
154         final DetailAST mods = aAST.findFirstToken(TokenTypes.MODIFIERS);
155         final Scope declaredScope = ScopeUtils.getScopeFromMods(mods);
156         final Scope typeScope =
157             ScopeUtils.inInterfaceBlock(aAST) ? Scope.PUBLIC : declaredScope;
158         if (typeScope.isIn(mScope)) {
159             final Scope surroundingScope = ScopeUtils.getSurroundingScope(aAST);
160             if ((surroundingScope == null) || surroundingScope.isIn(mScope)) {
161                 final FileContents contents = getFileContents();
162                 final int lineNo = aAST.getLineNo();
163                 final String[] cmt =
164                     contents.getJavadocBefore(lineNo);
165                 if (cmt == null) {
166                     log(lineNo, "javadoc.missing");
167                 }
168                 else if (ScopeUtils.isOuterMostType(aAST)) {
169                     // don't check author/version for inner classes
170                     checkTag(lineNo, cmt, "@author",
171                             mAuthorTagRE, mAuthorFormatRE, mAuthorFormat);
172                     checkTag(lineNo, cmt, "@version",
173                             mVersionTagRE, mVersionFormatRE, mVersionFormat);
174                 }
175             }
176         }
177     }
178 
179     /**
180      * Verifies that a type definition has a required tag.
181      * @param aLineNo the line number for the type definition.
182      * @param aCmt the Javadoc comment for the type definition.
183      * @param aTag the required tag name.
184      * @param aTagRE regexp for the full tag.
185      * @param aFormatRE regexp for the tag value.
186      * @param aFormat pattern for the tag value.
187      */
188     private void checkTag(
189             int aLineNo,
190             String[] aCmt,
191             String aTag,
192             RE aTagRE,
193             RE aFormatRE,
194             String aFormat)
195     {
196         if (aTagRE == null) {
197             return;
198         }
199 
200         int tagCount = 0;
201         for (int i = 0; i < aCmt.length; i++) {
202             final String s = aCmt[i];
203             if (aTagRE.match(s)) {
204                 tagCount += 1;
205                 final int contentStart = aTagRE.getParenStart(1);
206                 final String content = s.substring(contentStart);
207                 if (!aFormatRE.match(content)) {
208                     log(aLineNo, "type.tagFormat", aTag, aFormat);
209                 }
210 
211             }
212         }
213         if (tagCount == 0) {
214             log(aLineNo, "type.missingTag", aTag);
215         }
216 
217     }
218 
219 }