View Javadoc
1   /*
2    * SPDX-FileCopyrightText: Copyright (c) 2011-2026 Yegor Bugayenko
3    * SPDX-License-Identifier: MIT
4    */
5   package com.qulice.checkstyle;
6   
7   import com.jcabi.log.Logger;
8   import com.puppycrawl.tools.checkstyle.api.AuditEvent;
9   import com.puppycrawl.tools.checkstyle.api.AuditListener;
10  import com.qulice.spi.Environment;
11  import com.qulice.spi.Relative;
12  import java.io.File;
13  import java.util.Collections;
14  import java.util.LinkedList;
15  import java.util.List;
16  
17  /**
18   * Listener of Checkstyle events.
19   * @since 0.3
20   * @checkstyle ClassDataAbstractionCoupling (260 lines)
21   */
22  final class CheckstyleListener implements AuditListener {
23  
24      /**
25       * Environment.
26       */
27      private final Environment env;
28  
29      /**
30       * Collection of events collected.
31       */
32      private final List<AuditEvent> all;
33  
34      /**
35       * Public ctor.
36       * @param environ The environment
37       */
38      CheckstyleListener(final Environment environ) {
39          this.all = new LinkedList<>();
40          this.env = environ;
41      }
42  
43      @Override
44      public void auditStarted(final AuditEvent event) {
45          // intentionally empty
46      }
47  
48      @Override
49      public void auditFinished(final AuditEvent event) {
50          // intentionally empty
51      }
52  
53      @Override
54      public void fileStarted(final AuditEvent event) {
55          // intentionally empty
56      }
57  
58      @Override
59      public void fileFinished(final AuditEvent event) {
60          // intentionally empty
61      }
62  
63      @Override
64      public void addError(final AuditEvent event) {
65          final String path = new Relative(
66              this.env.basedir(), new File(event.getFileName())
67          ).path();
68          if (!this.env.exclude("checkstyle", path)
69              && !this.skipJavadocPackage(event, path)) {
70              this.all.add(event);
71          }
72      }
73  
74      @Override
75      public void addException(final AuditEvent event,
76          final Throwable throwable) {
77          final String check = event.getSourceName();
78          Logger.error(
79              this,
80              "%s[%d]: %s (%s), %[exception]s",
81              new Relative(
82                  this.env.basedir(), new File(event.getFileName())
83              ).path(),
84              event.getLine(),
85              event.getMessage(),
86              check.substring(check.lastIndexOf('.') + 1),
87              throwable
88          );
89      }
90  
91      /**
92       * Get all events.
93       * @return List of events
94       */
95      List<AuditEvent> events() {
96          return Collections.unmodifiableList(this.all);
97      }
98  
99      /**
100      * Suppress {@code JavadocPackage} on {@code src/test/java} files when the
101      * parallel {@code src/main/java} package already declares
102      * {@code package-info.java}. See <a
103      * href="https://github.com/yegor256/qulice/issues/865">#865</a>.
104      * @param event The audit event being reported
105      * @param path Project-relative path of the file under audit
106      * @return TRUE if the event should be discarded
107      */
108     private boolean skipJavadocPackage(final AuditEvent event, final String path) {
109         final String marker = "src/test/java/";
110         final String unix = path.replace(File.separatorChar, '/');
111         final int idx = unix.indexOf(marker);
112         boolean skip = false;
113         if (event.getSourceName().endsWith(".JavadocPackageCheck") && idx >= 0) {
114             final String tail = unix.substring(idx + marker.length());
115             final int slash = tail.lastIndexOf('/');
116             if (slash > 0) {
117                 final File main = new File(
118                     this.env.basedir(),
119                     String.format(
120                         "%ssrc/main/java/%s/package-info.java",
121                         unix.substring(0, idx),
122                         tail.substring(0, slash)
123                     )
124                 );
125                 skip = main.isFile();
126             }
127         }
128         return skip;
129     }
130 }