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

pmd / pmd / 380

29 Jan 2026 03:55PM UTC coverage: 78.964%. Remained the same
380

push

github

adangel
[doc] ADR 3: Clarify javadoc tags (#6392)

18537 of 24358 branches covered (76.1%)

Branch coverage included in aggregate %.

40391 of 50268 relevant lines covered (80.35%)

0.81 hits per line

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

61.98
/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDConfiguration.java
1
/*
2
 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3
 */
4

5
package net.sourceforge.pmd.cpd;
6

7
import java.beans.IntrospectionException;
8
import java.beans.PropertyDescriptor;
9
import java.lang.reflect.Method;
10
import java.nio.charset.Charset;
11
import java.util.Collections;
12
import java.util.HashMap;
13
import java.util.Locale;
14
import java.util.Map;
15
import java.util.Set;
16

17
import org.checkerframework.checker.nullness.qual.NonNull;
18
import org.checkerframework.checker.nullness.qual.Nullable;
19
import org.slf4j.LoggerFactory;
20

21
import net.sourceforge.pmd.AbstractConfiguration;
22
import net.sourceforge.pmd.cpd.internal.CpdLanguagePropertiesDefaults;
23
import net.sourceforge.pmd.lang.Language;
24
import net.sourceforge.pmd.lang.LanguageRegistry;
25
import net.sourceforge.pmd.util.log.internal.SimpleMessageReporter;
26

27
/**
28
 * @author Brian Remedios
29
 * @author Romain Pelisse - <belaran@gmail.com>
30
 */
31
public class CPDConfiguration extends AbstractConfiguration {
32

33
    public static final String DEFAULT_LANGUAGE = "java";
34
    public static final String DEFAULT_RENDERER = "text";
35

36
    private static final Map<String, Class<? extends CPDReportRenderer>> RENDERERS = new HashMap<>();
1✔
37

38

39
    static {
40
        RENDERERS.put(DEFAULT_RENDERER, SimpleRenderer.class);
1✔
41
        RENDERERS.put("xml", XMLRenderer.class);
1✔
42
        RENDERERS.put("xmlold", XMLOldRenderer.class);
1✔
43
        RENDERERS.put("csv", CSVRenderer.class);
1✔
44
        RENDERERS.put("csv_with_linecount_per_file", CSVWithLinecountPerFileRenderer.class);
1✔
45
        RENDERERS.put("vs", VSRenderer.class);
1✔
46
        RENDERERS.put("markdown", MarkdownRenderer.class);
1✔
47
    }
1✔
48

49

50
    private int minimumTileSize;
51

52
    private boolean skipDuplicates;
53

54
    private String rendererName = DEFAULT_RENDERER;
1✔
55

56
    private @Nullable CPDReportRenderer cpdReportRenderer;
57

58
    private boolean ignoreLiterals;
59

60
    private boolean ignoreIdentifiers;
61

62
    private boolean ignoreAnnotations;
63

64
    private boolean ignoreUsings;
65

66
    private boolean ignoreLiteralSequences = false;
1✔
67

68
    private boolean ignoreIdentifierAndLiteralSequences = false;
1✔
69

70
    /**
71
     * @deprecated Since 7.3.0.
72
     */
73
    @Deprecated
1✔
74
    // Note: The default value was false until up to 7.3.0 and is true since 7.4.0
75
    private boolean skipLexicalErrors = true;
76

77
    private boolean noSkipBlocks = false;
1✔
78

79
    private String skipBlocksPattern = CpdLanguagePropertiesDefaults.DEFAULT_SKIP_BLOCKS_PATTERN;
1✔
80

81
    private boolean help;
82

83

84
    public CPDConfiguration() {
85
        this(LanguageRegistry.CPD);
1✔
86
    }
1✔
87

88
    public CPDConfiguration(LanguageRegistry languageRegistry) {
89
        super(languageRegistry, new SimpleMessageReporter(LoggerFactory.getLogger(CpdAnalysis.class)));
1✔
90
    }
1✔
91

92
    @Override
93
    public void setSourceEncoding(Charset sourceEncoding) {
94
        super.setSourceEncoding(sourceEncoding);
1✔
95
        if (cpdReportRenderer != null) {
1✔
96
            setRendererEncoding(cpdReportRenderer, sourceEncoding);
1✔
97
        }
98
    }
1✔
99

100
    static CPDReportRenderer createRendererByName(String name, Charset encoding) {
101
        if (name == null || "".equals(name)) {
1!
102
            name = DEFAULT_RENDERER;
×
103
        }
104
        Class<? extends CPDReportRenderer> rendererClass = RENDERERS.get(name.toLowerCase(Locale.ROOT));
1✔
105
        if (rendererClass == null) {
1!
106
            Class<?> klass;
107
            try {
108
                klass = Class.forName(name);
×
109
                if (CPDReportRenderer.class.isAssignableFrom(klass)) {
×
110
                    rendererClass = (Class) klass;
×
111
                } else {
112
                    throw new IllegalArgumentException("Class " + name + " does not implement " + CPDReportRenderer.class);
×
113
                }
114
            } catch (ClassNotFoundException e) {
×
115
                throw new IllegalArgumentException("Cannot find class " + name);
×
116
            }
×
117
        }
118

119
        CPDReportRenderer renderer;
120
        try {
121
            renderer = rendererClass.getDeclaredConstructor().newInstance();
1✔
122
            setRendererEncoding(renderer, encoding);
1✔
123
        } catch (Exception e) {
×
124
            System.err.println("Couldn't instantiate renderer, defaulting to SimpleRenderer: " + e);
×
125
            renderer = new SimpleRenderer();
×
126
        }
1✔
127
        return renderer;
1✔
128
    }
129

130
    private static void setRendererEncoding(@NonNull Object renderer, Charset encoding) {
131
        try {
132
            PropertyDescriptor encodingProperty = new PropertyDescriptor("encoding", renderer.getClass());
1✔
133
            Method method = encodingProperty.getWriteMethod();
1✔
134
            if (method == null) {
1!
135
                return;
×
136
            }
137
            if (method.getParameterTypes()[0] == Charset.class) {
1!
138
                method.invoke(renderer, encoding);
×
139
            } else if (method.getParameterTypes()[0] == String.class) {
1!
140
                method.invoke(renderer, encoding.name());
1✔
141
            }
142
        } catch (IntrospectionException | ReflectiveOperationException ignored) {
1✔
143
            // ignored - maybe this renderer doesn't have a encoding property
144
        }
1✔
145
    }
1✔
146

147
    public static Set<String> getRenderers() {
148
        return Collections.unmodifiableSet(RENDERERS.keySet());
×
149
    }
150

151
    public int getMinimumTileSize() {
152
        return minimumTileSize;
1✔
153
    }
154

155
    public void setMinimumTileSize(int minimumTileSize) {
156
        this.minimumTileSize = minimumTileSize;
1✔
157
    }
1✔
158

159
    public boolean isSkipDuplicates() {
160
        return skipDuplicates;
1✔
161
    }
162

163
    public void setSkipDuplicates(boolean skipDuplicates) {
164
        this.skipDuplicates = skipDuplicates;
1✔
165
    }
1✔
166

167
    public String getRendererName() {
168
        return rendererName;
×
169
    }
170

171
    public void setRendererName(String rendererName) {
172
        this.rendererName = rendererName;
1✔
173
        if (rendererName == null) {
1!
174
            this.cpdReportRenderer = null;
×
175
        }
176
        this.cpdReportRenderer = createRendererByName(rendererName, getSourceEncoding());
1✔
177
    }
1✔
178

179

180
    public CPDReportRenderer getCPDReportRenderer() {
181
        return cpdReportRenderer;
1✔
182
    }
183

184
    void setRenderer(CPDReportRenderer renderer) {
185
        this.cpdReportRenderer = renderer;
×
186
    }
×
187

188
    public boolean isIgnoreLiterals() {
189
        return ignoreLiterals;
1✔
190
    }
191

192
    public void setIgnoreLiterals(boolean ignoreLiterals) {
193
        this.ignoreLiterals = ignoreLiterals;
×
194
    }
×
195

196
    public boolean isIgnoreIdentifiers() {
197
        return ignoreIdentifiers;
1✔
198
    }
199

200
    public void setIgnoreIdentifiers(boolean ignoreIdentifiers) {
201
        this.ignoreIdentifiers = ignoreIdentifiers;
×
202
    }
×
203

204
    public boolean isIgnoreAnnotations() {
205
        return ignoreAnnotations;
1✔
206
    }
207

208
    public void setIgnoreAnnotations(boolean ignoreAnnotations) {
209
        this.ignoreAnnotations = ignoreAnnotations;
×
210
    }
×
211

212
    public boolean isIgnoreUsings() {
213
        return ignoreUsings;
1✔
214
    }
215

216
    public void setIgnoreUsings(boolean ignoreUsings) {
217
        this.ignoreUsings = ignoreUsings;
×
218
    }
×
219

220
    public boolean isIgnoreLiteralSequences() {
221
        return ignoreLiteralSequences;
1✔
222
    }
223

224
    public void setIgnoreLiteralSequences(boolean ignoreLiteralSequences) {
225
        this.ignoreLiteralSequences = ignoreLiteralSequences;
×
226
    }
×
227

228
    public boolean isIgnoreIdentifierAndLiteralSequences() {
229
        return ignoreIdentifierAndLiteralSequences;
1✔
230
    }
231

232
    public void setIgnoreIdentifierAndLiteralSequences(boolean ignoreIdentifierAndLiteralSequences) {
233
        this.ignoreIdentifierAndLiteralSequences = ignoreIdentifierAndLiteralSequences;
×
234
    }
×
235

236
    /**
237
     * @deprecated Since 7.3.0. This option will be removed. With {@link #isFailOnError()}, you can
238
     * control whether lexical errors should fail the build or not.
239
     */
240
    @Deprecated
241
    public boolean isSkipLexicalErrors() {
242
        return skipLexicalErrors;
1✔
243
    }
244

245
    /**
246
     * @deprecated Since 7.3.0. This option will be removed. With {@link #setFailOnError(boolean)}, you can
247
     * control whether lexical errors should fail the build or not.
248
     */
249
    @Deprecated
250
    public void setSkipLexicalErrors(boolean skipLexicalErrors) {
251
        this.skipLexicalErrors = skipLexicalErrors;
1✔
252
    }
1✔
253

254
    public boolean isHelp() {
255
        return help;
×
256
    }
257

258
    public void setHelp(boolean help) {
259
        this.help = help;
×
260
    }
×
261

262
    public boolean isNoSkipBlocks() {
263
        return noSkipBlocks;
1✔
264
    }
265

266
    public void setNoSkipBlocks(boolean noSkipBlocks) {
267
        this.noSkipBlocks = noSkipBlocks;
×
268
    }
×
269

270
    public String getSkipBlocksPattern() {
271
        return skipBlocksPattern;
1✔
272
    }
273

274
    public void setSkipBlocksPattern(String skipBlocksPattern) {
275
        this.skipBlocksPattern = skipBlocksPattern;
×
276
    }
×
277

278
    @Override
279
    protected void checkLanguageIsAcceptable(Language lang) throws UnsupportedOperationException {
280
        if (!(lang instanceof CpdCapableLanguage)) {
1✔
281
            throw new UnsupportedOperationException("Language " + lang.getId() + " does not support analysis with CPD and cannot be used in a CPDConfiguration. "
1✔
282
                + "You may be able to use it with PMD though.");
283
        }
284
    }
1✔
285

286

287
}
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