• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pmd / pmd / 23

30 May 2025 04:25PM UTC coverage: 78.377% (-0.2%) from 78.601%
23

push

github

adangel
[core] Add rule to report unnecessary suppression comments/annotations (#5609)

Merge pull request #5609 from oowekyala:new-rule-UnnecessarySuppression

17712 of 23434 branches covered (75.58%)

Branch coverage included in aggregate %.

159 of 328 new or added lines in 22 files covered. (48.48%)

36 existing lines in 4 files now uncovered.

38902 of 48799 relevant lines covered (79.72%)

0.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.37
/pmd-core/src/main/java/net/sourceforge/pmd/lang/impl/MultiThreadProcessor.java
1
/*
2
 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3
 */
4

5
package net.sourceforge.pmd.lang.impl;
6

7
import java.util.LinkedList;
8
import java.util.List;
9
import java.util.concurrent.ExecutionException;
10
import java.util.concurrent.ExecutorService;
11
import java.util.concurrent.Executors;
12
import java.util.concurrent.Future;
13
import java.util.concurrent.TimeUnit;
14

15
import org.slf4j.event.Level;
16

17
import net.sourceforge.pmd.lang.LanguageProcessor.AnalysisTask;
18
import net.sourceforge.pmd.lang.document.TextFile;
19
import net.sourceforge.pmd.lang.rule.internal.RuleSets;
20
import net.sourceforge.pmd.util.log.PmdReporter;
21

22

23
/**
24
 * @author Romain Pelisse <belaran@gmail.com>
25
 */
26
final class MultiThreadProcessor extends AbstractPMDProcessor {
27
    private final ExecutorService executor;
28

29
    private final List<Future<?>> futureList;
30

31
    MultiThreadProcessor(final AnalysisTask task) {
32
        super(task);
1✔
33
        int threadCount = task.getThreadCount();
1✔
34
        if (threadCount == 1) {
1✔
35
            task.getMessageReporter().log(Level.DEBUG, "Using 1 thread for analysis");
1✔
36
        } else {
37
            task.getMessageReporter().log(Level.DEBUG, "Using {0} threads for analysis", threadCount);
1✔
38
        }
39
        executor = Executors.newFixedThreadPool(threadCount, new PmdThreadFactory());
1✔
40
        futureList = new LinkedList<>();
1✔
41
    }
1✔
42

43
    @Override
44
    @SuppressWarnings("PMD.CloseResource") // closed by the PMDRunnable
45
    public void processFiles() {
46
        // The thread-local is not static, but analysis-global
47
        // This means we don't have to reset it manually, every analysis is isolated.
48
        // The initial value makes a copy of the rulesets
49
        final ThreadLocal<RuleSets> ruleSetCopy = ThreadLocal.withInitial(() -> {
1✔
50
            RuleSets copy = new RuleSets(task.getRulesets());
1✔
51
            // use a noop reporter because the copy should only contain rules that
52
            // initialized properly
53
            copy.initializeRules(task.getLpRegistry(), PmdReporter.quiet());
1✔
54
            return copy;
1✔
55
        });
56

57
        for (final TextFile textFile : task.getFiles()) {
1✔
58
            futureList.add(executor.submit(new PmdRunnable(textFile, task) {
1✔
59
                @Override
60
                protected RuleSets getRulesets() {
61
                    return ruleSetCopy.get();
1✔
62
                }
63
            }));
64
        }
1✔
65
    }
1✔
66

67
    @Override
68
    public void close() {
69
        try {
70
            try {
71
                for (Future<?> task : futureList) {
1✔
72
                    task.get();
1✔
73
                }
1✔
74
            } catch (ExecutionException e) {
1✔
75
                task.getMessageReporter().error("Unknown error occurred while executing a PmdRunnable: {0}",
1✔
76
                        e.getCause().toString(), e.getCause());
1✔
77
                if (e.getCause() instanceof Error) {
1!
78
                    throw (Error) e.getCause();
1✔
79
                }
80
            }
1✔
81

82
            executor.shutdown();
1✔
83
            while (!executor.awaitTermination(10, TimeUnit.HOURS)) {
1!
84
                // still waiting
UNCOV
85
                Thread.yield();
×
86
            }
UNCOV
87
        } catch (InterruptedException e) {
×
UNCOV
88
            Thread.currentThread().interrupt();
×
89
        } finally {
90
            executor.shutdownNow();
1✔
91
        }
92
    }
1✔
93
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc