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

pmd / pmd / 142

09 Sep 2025 06:41PM UTC coverage: 78.598% (+0.005%) from 78.593%
142

push

github

adangel
 Add @judepereira as a contributor

18054 of 23809 branches covered (75.83%)

Branch coverage included in aggregate %.

39452 of 49356 relevant lines covered (79.93%)

0.81 hits per line

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

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

5
package net.sourceforge.pmd.renderers;
6

7
import java.io.IOException;
8
import java.util.ArrayList;
9
import java.util.HashMap;
10
import java.util.Iterator;
11
import java.util.List;
12
import java.util.Map;
13
import java.util.Set;
14

15
import org.apache.commons.lang3.StringUtils;
16
import org.checkerframework.checker.nullness.qual.NonNull;
17

18
import net.sourceforge.pmd.properties.PropertyDescriptor;
19
import net.sourceforge.pmd.properties.PropertyFactory;
20
import net.sourceforge.pmd.properties.PropertySource;
21
import net.sourceforge.pmd.renderers.ColumnDescriptor.Accessor;
22
import net.sourceforge.pmd.reporting.RuleViolation;
23
import net.sourceforge.pmd.util.CollectionUtil;
24

25

26
/**
27
 * Renderer the results to a comma-delimited text format. All available columns
28
 * are present by default. IDEs can enable/disable columns individually
29
 * (cmd-line control to follow eventually)
30
 */
31
public class CSVRenderer extends AbstractIncrementingRenderer {
32

33
    private final String separator;
34
    private final String cr;
35

36
    private CSVWriter<RuleViolation> csvWriter;
37

38
    private static final String DEFAULT_SEPARATOR = ",";
39

40
    private static final Map<String, PropertyDescriptor<Boolean>> PROPERTY_DESCRIPTORS_BY_ID = new HashMap<>();
1✔
41

42
    public static final String NAME = "csv";
43

44
    /** List of columns that are off by default. Can be enabled with the specific property. */
45
    private static final Set<String> DEFAULT_OFF = CollectionUtil.setOf("endLine", "beginColumn", "endColumn");
1✔
46

47
    @SuppressWarnings("unchecked")
1✔
48
    private final ColumnDescriptor<RuleViolation>[] allColumns = new ColumnDescriptor[]{
49
        newColDescriptor("problem", "Problem", (idx, rv, cr) -> Integer.toString(idx)),
1✔
50
        newColDescriptor("package", "Package", (idx, rv, cr) -> rv.getAdditionalInfo().getOrDefault(RuleViolation.PACKAGE_NAME, "")),
1✔
51
        newColDescriptor("file", "File", (idx, rv, cr) -> determineFileName(rv.getFileId())),
1✔
52
        newColDescriptor("priority", "Priority", (idx, rv, cr) -> Integer.toString(rv.getRule().getPriority().getPriority())),
1✔
53
        newColDescriptor("line", "Line", (idx, rv, cr) -> Integer.toString(rv.getBeginLine())),
1✔
54
        newColDescriptor("endLine", "End Line", (idx, rv, cr) -> Integer.toString(rv.getEndLine())),
1✔
55
        newColDescriptor("beginColumn", "Begin Column", (idx, rv, cr) -> Integer.toString(rv.getBeginColumn())),
1✔
56
        newColDescriptor("endColumn", "End Column", (idx, rv, cr) -> Integer.toString(rv.getEndColumn())),
1✔
57
        newColDescriptor("desc", "Description", (idx, rv, cr) -> StringUtils.replaceChars(rv.getDescription(), '\"', '\'')),
1✔
58
        newColDescriptor("ruleSet", "Rule set", (idx, rv, cr) -> rv.getRule().getRuleSetName()),
1✔
59
        newColDescriptor("rule", "Rule", (idx, rv, cr) -> rv.getRule().getName()),
1✔
60
    };
61

62
    private static @NonNull ColumnDescriptor<RuleViolation> newColDescriptor(String id, String title, Accessor<RuleViolation> accessor) {
63
        return new ColumnDescriptor<>(id, title, accessor);
1✔
64
    }
65

66
    public CSVRenderer(ColumnDescriptor<RuleViolation>[] columns, String theSeparator, String theCR) {
67
        super(NAME, "Comma-separated values tabular format.");
×
68

69
        separator = theSeparator;
×
70
        cr = theCR;
×
71

72
        for (ColumnDescriptor<RuleViolation> desc : columns) {
×
73
            definePropertyDescriptor(booleanPropertyFor(desc.id, desc.title));
×
74
        }
75
    }
×
76

77
    public CSVRenderer() {
78
        super(NAME, "Comma-separated values tabular format.");
1✔
79

80
        separator = DEFAULT_SEPARATOR;
1✔
81
        cr = System.lineSeparator();
1✔
82

83
        for (ColumnDescriptor<RuleViolation> desc : allColumns) {
1✔
84
            definePropertyDescriptor(booleanPropertyFor(desc.id, desc.title));
1✔
85
        }
86
    }
1✔
87

88
    private static PropertyDescriptor<Boolean> booleanPropertyFor(String id, String label) {
89

90
        PropertyDescriptor<Boolean> prop = PROPERTY_DESCRIPTORS_BY_ID.get(id);
1✔
91
        if (prop != null) {
1✔
92
            return prop;
1✔
93
        }
94

95
        prop = PropertyFactory.booleanProperty(id).defaultValue(!DEFAULT_OFF.contains(id)).desc("Include " + label + " column").build();
1✔
96
        PROPERTY_DESCRIPTORS_BY_ID.put(id, prop);
1✔
97
        return prop;
1✔
98
    }
99

100
    private List<ColumnDescriptor<RuleViolation>> activeColumns() {
101

102
        List<ColumnDescriptor<RuleViolation>> actives = new ArrayList<>();
1✔
103

104
        for (ColumnDescriptor<RuleViolation> desc : allColumns) {
1✔
105
            PropertyDescriptor<Boolean> prop = booleanPropertyFor(desc.id, null);
1✔
106
            if (getProperty(prop)) {
1✔
107
                actives.add(desc);
1✔
108
            }
109

110
        }
111
        return actives;
1✔
112
    }
113

114
    private CSVWriter<RuleViolation> csvWriter() {
115
        if (csvWriter != null) {
1✔
116
            return csvWriter;
1✔
117
        }
118

119
        csvWriter = new CSVWriter<>(activeColumns(), separator, cr);
1✔
120
        return csvWriter;
1✔
121
    }
122

123
    @Override
124
    public void start() throws IOException {
125
        csvWriter().writeTitles(getWriter());
1✔
126
    }
1✔
127

128
    @Override
129
    public String defaultFileExtension() {
130
        return "csv";
×
131
    }
132

133
    @Override
134
    public void renderFileViolations(Iterator<RuleViolation> violations) throws IOException {
135
        csvWriter().writeData(getWriter(), violations);
1✔
136
    }
1✔
137

138
    /**
139
     * We can't show any violations if we don't have any visible columns.
140
     *
141
     * @see PropertySource#dysfunctionReason()
142
     */
143
    @Override
144
    public String dysfunctionReason() {
145
        return activeColumns().isEmpty() ? "No columns selected" : null;
×
146
    }
147
}
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