View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2025 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.javadoc;
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.nio.file.Files;
25  import java.nio.file.Path;
26  import java.util.HashSet;
27  import java.util.Set;
28  
29  import com.puppycrawl.tools.checkstyle.GlobalStatefulCheck;
30  import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
31  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
32  import com.puppycrawl.tools.checkstyle.api.FileText;
33  
34  /**
35   * <div>
36   * Checks that each Java package has a Javadoc file used for commenting.
37   * By default, it only allows a {@code package-info.java} file,
38   * but can be configured to allow a {@code package.html} file.
39   * </div>
40   *
41   * <p>
42   * A violation will be reported if both files exist as this is not allowed by the Javadoc tool.
43   * </p>
44   *
45   * @since 5.0
46   */
47  @GlobalStatefulCheck
48  public class JavadocPackageCheck extends AbstractFileSetCheck {
49  
50      /**
51       * A key is pointing to the warning message text in "messages.properties"
52       * file.
53       */
54      public static final String MSG_LEGACY_PACKAGE_HTML = "javadoc.legacyPackageHtml";
55  
56      /**
57       * A key is pointing to the warning message text in "messages.properties"
58       * file.
59       */
60      public static final String MSG_PACKAGE_INFO = "javadoc.packageInfo";
61  
62      /** The directories checked. */
63      private final Set<File> directoriesChecked = new HashSet<>();
64  
65      /** Allow legacy {@code package.html} file to be used. */
66      private boolean allowLegacy;
67  
68      /**
69       * Creates a new instance.
70       */
71      public JavadocPackageCheck() {
72          // java, not html!
73          // The rule is: Every JAVA file should have a package.html sibling
74          setFileExtensions("java");
75      }
76  
77      /**
78       * Setter to specify the file extensions of the files to process.
79       *
80       * @param extensions the set of file extensions. A missing
81       *         initial '.' character of an extension is automatically added.
82       * @throws IllegalArgumentException is argument is null
83       */
84      @Override
85      public final void setFileExtensions(String... extensions) {
86          super.setFileExtensions(extensions);
87      }
88  
89      @Override
90      protected void processFiltered(File file, FileText fileText) throws CheckstyleException {
91          // Check if already processed directory
92          final File dir;
93          try {
94              dir = file.getCanonicalFile().getParentFile();
95          }
96          catch (IOException exc) {
97              throw new CheckstyleException(
98                      "Exception while getting canonical path to file " + file.getPath(), exc);
99          }
100         final boolean isDirChecked = !directoriesChecked.add(dir);
101         if (!isDirChecked) {
102             // Check for the preferred file.
103             final Path packageInfo = Path.of(dir.getPath(), "package-info.java");
104             final Path packageHtml = Path.of(dir.getPath(), "package.html");
105 
106             if (Files.exists(packageInfo)) {
107                 if (Files.exists(packageHtml)) {
108                     log(1, MSG_LEGACY_PACKAGE_HTML);
109                 }
110             }
111             else if (!allowLegacy || !Files.exists(packageHtml)) {
112                 log(1, MSG_PACKAGE_INFO);
113             }
114         }
115     }
116 
117     /**
118      * Setter to allow legacy {@code package.html} file to be used.
119      *
120      * @param allowLegacy whether to allow support.
121      * @since 5.0
122      */
123     public void setAllowLegacy(boolean allowLegacy) {
124         this.allowLegacy = allowLegacy;
125     }
126 
127 }