UniquePropertiesCheck.java

1
////////////////////////////////////////////////////////////////////////////////
2
// checkstyle: Checks Java source code for adherence to a set of rules.
3
// Copyright (C) 2001-2017 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;
21
22
import java.io.File;
23
import java.io.FileInputStream;
24
import java.io.IOException;
25
import java.util.Properties;
26
import java.util.regex.Matcher;
27
import java.util.regex.Pattern;
28
29
import com.google.common.collect.HashMultiset;
30
import com.google.common.collect.ImmutableMultiset;
31
import com.google.common.collect.Multiset;
32
import com.google.common.collect.Multiset.Entry;
33
import com.google.common.io.Closeables;
34
import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
35
import com.puppycrawl.tools.checkstyle.api.FileText;
36
37
/**
38
 * Checks the uniqueness of property keys (left from equal sign) in the
39
 * properties file.
40
 *
41
 * @author Pavel Baranchikov
42
 */
43
public class UniquePropertiesCheck extends AbstractFileSetCheck {
44
45
    /**
46
     * Localization key for check violation.
47
     */
48
    public static final String MSG_KEY = "properties.duplicate.property";
49
    /**
50
     * Localization key for IO exception occurred on file open.
51
     */
52
    public static final String MSG_IO_EXCEPTION_KEY = "unable.open.cause";
53
54
    /**
55
     * Pattern matching single space.
56
     */
57
    private static final Pattern SPACE_PATTERN = Pattern.compile(" ");
58
59
    /**
60
     * Construct the check with default values.
61
     */
62
    public UniquePropertiesCheck() {
63 1 1. : removed call to com/puppycrawl/tools/checkstyle/checks/UniquePropertiesCheck::setFileExtensions → KILLED
        setFileExtensions("properties");
64
    }
65
66
    @Override
67
    protected void processFiltered(File file, FileText fileText) {
68
        final UniqueProperties properties = new UniqueProperties();
69
        FileInputStream fileInputStream = null;
70
        try {
71
            fileInputStream = new FileInputStream(file);
72 1 1. processFiltered : removed call to com/puppycrawl/tools/checkstyle/checks/UniquePropertiesCheck$UniqueProperties::load → KILLED
            properties.load(fileInputStream);
73
        }
74
        catch (IOException ex) {
75 1 1. processFiltered : removed call to com/puppycrawl/tools/checkstyle/checks/UniquePropertiesCheck::log → KILLED
            log(0, MSG_IO_EXCEPTION_KEY, file.getPath(),
76
                    ex.getLocalizedMessage());
77
        }
78
        finally {
79 1 1. processFiltered : removed call to com/google/common/io/Closeables::closeQuietly → KILLED
            Closeables.closeQuietly(fileInputStream);
80
        }
81
82 1 1. processFiltered : negated conditional → KILLED
        for (Entry<String> duplication : properties
83
                .getDuplicatedKeys().entrySet()) {
84
            final String keyName = duplication.getElement();
85
            final int lineNumber = getLineNumber(fileText, keyName);
86
            // Number of occurrences is number of duplications + 1
87 2 1. processFiltered : Replaced integer addition with subtraction → KILLED
2. processFiltered : removed call to com/puppycrawl/tools/checkstyle/checks/UniquePropertiesCheck::log → KILLED
            log(lineNumber, MSG_KEY, keyName, duplication.getCount() + 1);
88
        }
89
    }
90
91
    /**
92
     * Method returns line number the key is detected in the checked properties
93
     * files first.
94
     *
95
     * @param fileText
96
     *            {@link FileText} object contains the lines to process
97
     * @param keyName
98
     *            key name to look for
99
     * @return line number of first occurrence. If no key found in properties
100
     *         file, 0 is returned
101
     */
102
    private static int getLineNumber(FileText fileText, String keyName) {
103
        final Pattern keyPattern = getKeyPattern(keyName);
104
        int lineNumber = 1;
105
        final Matcher matcher = keyPattern.matcher("");
106 3 1. getLineNumber : changed conditional boundary → KILLED
2. getLineNumber : Changed increment from 1 to -1 → KILLED
3. getLineNumber : negated conditional → KILLED
        for (int index = 0; index < fileText.size(); index++) {
107
            final String line = fileText.get(index);
108
            matcher.reset(line);
109 1 1. getLineNumber : negated conditional → KILLED
            if (matcher.matches()) {
110
                break;
111
            }
112 1 1. getLineNumber : Changed increment from 1 to -1 → KILLED
            ++lineNumber;
113
        }
114
        // -1 as check seeks for the first duplicate occurance in file,
115
        // so it cannot be the last line.
116 3 1. getLineNumber : changed conditional boundary → KILLED
2. getLineNumber : Replaced integer subtraction with addition → KILLED
3. getLineNumber : negated conditional → KILLED
        if (lineNumber > fileText.size() - 1) {
117
            lineNumber = 0;
118
        }
119 1 1. getLineNumber : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return lineNumber;
120
    }
121
122
    /**
123
     * Method returns regular expression pattern given key name.
124
     *
125
     * @param keyName
126
     *            key name to look for
127
     * @return regular expression pattern given key name
128
     */
129
    private static Pattern getKeyPattern(String keyName) {
130
        final String keyPatternString = "^" + SPACE_PATTERN.matcher(keyName)
131
                .replaceAll(Matcher.quoteReplacement("\\\\ ")) + "[\\s:=].*$";
132 1 1. getKeyPattern : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/UniquePropertiesCheck::getKeyPattern to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return Pattern.compile(keyPatternString);
133
    }
134
135
    /**
136
     * Properties subclass to store duplicated property keys in a separate map.
137
     *
138
     * @author Pavel Baranchikov
139
     * @noinspection ClassExtendsConcreteCollection, SerializableHasSerializationMethods
140
     */
141
    private static class UniqueProperties extends Properties {
142
        private static final long serialVersionUID = 1L;
143
        /**
144
         * Multiset, holding duplicated keys. Keys are added here only if they
145
         * already exist in Properties' inner map.
146
         */
147
        private final Multiset<String> duplicatedKeys = HashMultiset
148
                .create();
149
150
        /**
151
         * Puts the value into properties by the key specified.
152
         * @noinspection UseOfPropertiesAsHashtable
153
         */
154
        @Override
155
        public synchronized Object put(Object key, Object value) {
156
            final Object oldValue = super.put(key, value);
157
            if (oldValue != null && key instanceof String) {
158
                final String keyString = (String) key;
159
                duplicatedKeys.add(keyString);
160
            }
161
            return oldValue;
162
        }
163
164
        /**
165
         * Retrieves a collections of duplicated properties keys.
166
         *
167
         * @return A collection of duplicated keys.
168
         */
169
        public Multiset<String> getDuplicatedKeys() {
170
            return ImmutableMultiset.copyOf(duplicatedKeys);
171
        }
172
    }
173
}

Mutations

63

1.1
Location :
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testShouldNotProcessFilesWithWrongFileExtension(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/UniquePropertiesCheck::setFileExtensions → KILLED

72

1.1
Location : processFiltered
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/UniquePropertiesCheck$UniqueProperties::load → KILLED

75

1.1
Location : processFiltered
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testIoException(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/UniquePropertiesCheck::log → KILLED

79

1.1
Location : processFiltered
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testCloseInputStream(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
removed call to com/google/common/io/Closeables::closeQuietly → KILLED

82

1.1
Location : processFiltered
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testIoException(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
negated conditional → KILLED

87

1.1
Location : processFiltered
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
Replaced integer addition with subtraction → KILLED

2.2
Location : processFiltered
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/UniquePropertiesCheck::log → KILLED

106

1.1
Location : getLineNumber
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testNotFoundKey(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
changed conditional boundary → KILLED

2.2
Location : getLineNumber
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testNotFoundKey(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
Changed increment from 1 to -1 → KILLED

3.3
Location : getLineNumber
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testNotFoundKey(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
negated conditional → KILLED

109

1.1
Location : getLineNumber
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testNotFoundKey(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
negated conditional → KILLED

112

1.1
Location : getLineNumber
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testNotFoundKey(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
Changed increment from 1 to -1 → KILLED

116

1.1
Location : getLineNumber
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testDuplicatedProperty(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
changed conditional boundary → KILLED

2.2
Location : getLineNumber
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testNotFoundKey(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
Replaced integer subtraction with addition → KILLED

3.3
Location : getLineNumber
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testNotFoundKey(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
negated conditional → KILLED

119

1.1
Location : getLineNumber
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testNotFoundKey(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

132

1.1
Location : getKeyPattern
Killed by : com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest.testNotFoundKey(com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheckTest)
mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/UniquePropertiesCheck::getKeyPattern to ( if (x != null) null else throw new RuntimeException ) → KILLED

Active mutators

Tests examined


Report generated by PIT 1.2.2