NewlineAtEndOfFileCheck.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.IOException;
24
import java.io.RandomAccessFile;
25
import java.util.Locale;
26
27
import com.google.common.io.Closeables;
28
import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
29
import com.puppycrawl.tools.checkstyle.api.FileText;
30
31
/**
32
 * <p>
33
 * Checks that there is a newline at the end of each file.
34
 * </p>
35
 * <p>
36
 * An example of how to configure the check is:
37
 * </p>
38
 * <pre>
39
 * &lt;module name="NewlineAtEndOfFile"/&gt;</pre>
40
 * <p>
41
 * This will check against the platform-specific default line separator.
42
 * </p>
43
 * <p>
44
 * It is also possible to enforce the use of a specific line-separator across
45
 * platforms, with the 'lineSeparator' property:
46
 * </p>
47
 * <pre>
48
 * &lt;module name="NewlineAtEndOfFile"&gt;
49
 *   &lt;property name="lineSeparator" value="lf"/&gt;
50
 * &lt;/module&gt;</pre>
51
 * <p>
52
 * Valid values for the 'lineSeparator' property are 'system' (system default),
53
 * 'crlf' (windows), 'cr' (mac), 'lf' (unix) and 'lf_cr_crlf' (lf, cr or crlf).
54
 * </p>
55
 *
56
 * @author Christopher Lenz
57
 * @author lkuehne
58
 */
59
public class NewlineAtEndOfFileCheck
60
    extends AbstractFileSetCheck {
61
62
    /**
63
     * A key is pointing to the warning message text in "messages.properties"
64
     * file.
65
     */
66
    public static final String MSG_KEY_UNABLE_OPEN = "unable.open";
67
68
    /**
69
     * A key is pointing to the warning message text in "messages.properties"
70
     * file.
71
     */
72
    public static final String MSG_KEY_NO_NEWLINE_EOF = "noNewlineAtEOF";
73
74
    /** The line separator to check against. */
75
    private LineSeparatorOption lineSeparator = LineSeparatorOption.SYSTEM;
76
77
    @Override
78
    protected void processFiltered(File file, FileText fileText) {
79
        try {
80 1 1. processFiltered : removed call to com/puppycrawl/tools/checkstyle/checks/NewlineAtEndOfFileCheck::readAndCheckFile → KILLED
            readAndCheckFile(file);
81
        }
82
        catch (final IOException ignored) {
83 1 1. processFiltered : removed call to com/puppycrawl/tools/checkstyle/checks/NewlineAtEndOfFileCheck::log → KILLED
            log(0, MSG_KEY_UNABLE_OPEN, file.getPath());
84
        }
85
    }
86
87
    /**
88
     * Sets the line separator to one of 'crlf', 'lf','cr', 'lf_cr_crlf' or 'system'.
89
     *
90
     * @param lineSeparatorParam The line separator to set
91
     * @throws IllegalArgumentException If the specified line separator is not
92
     *         one of 'crlf', 'lf', 'cr', 'lf_cr_crlf' or 'system'
93
     */
94
    public void setLineSeparator(String lineSeparatorParam) {
95
        try {
96
            lineSeparator =
97
                Enum.valueOf(LineSeparatorOption.class, lineSeparatorParam.trim()
98
                    .toUpperCase(Locale.ENGLISH));
99
        }
100
        catch (IllegalArgumentException iae) {
101
            throw new IllegalArgumentException("unable to parse " + lineSeparatorParam, iae);
102
        }
103
    }
104
105
    /**
106
     * Reads the file provided and checks line separators.
107
     * @param file the file to be processed
108
     * @throws IOException When an IO error occurred while reading from the
109
     *         file provided
110
     */
111
    private void readAndCheckFile(File file) throws IOException {
112
        // Cannot use lines as the line separators have been removed!
113
        final RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
114
        boolean threw = true;
115
        try {
116 1 1. readAndCheckFile : negated conditional → KILLED
            if (!endsWithNewline(randomAccessFile)) {
117 1 1. readAndCheckFile : removed call to com/puppycrawl/tools/checkstyle/checks/NewlineAtEndOfFileCheck::log → KILLED
                log(0, MSG_KEY_NO_NEWLINE_EOF, file.getPath());
118
            }
119
            threw = false;
120
        }
121
        finally {
122 1 1. readAndCheckFile : removed call to com/google/common/io/Closeables::close → KILLED
            Closeables.close(randomAccessFile, threw);
123
        }
124
    }
125
126
    /**
127
     * Checks whether the content provided by the Reader ends with the platform
128
     * specific line separator.
129
     * @param randomAccessFile The reader for the content to check
130
     * @return boolean Whether the content ends with a line separator
131
     * @throws IOException When an IO error occurred while reading from the
132
     *         provided reader
133
     */
134
    private boolean endsWithNewline(RandomAccessFile randomAccessFile)
135
            throws IOException {
136
        final boolean result;
137
        final int len = lineSeparator.length();
138 2 1. endsWithNewline : changed conditional boundary → KILLED
2. endsWithNewline : negated conditional → KILLED
        if (randomAccessFile.length() < len) {
139
            result = false;
140
        }
141
        else {
142 2 1. endsWithNewline : Replaced long subtraction with addition → KILLED
2. endsWithNewline : removed call to java/io/RandomAccessFile::seek → KILLED
            randomAccessFile.seek(randomAccessFile.length() - len);
143
            final byte[] lastBytes = new byte[len];
144
            final int readBytes = randomAccessFile.read(lastBytes);
145 1 1. endsWithNewline : negated conditional → KILLED
            if (readBytes != len) {
146
                throw new IOException("Unable to read " + len + " bytes, got "
147
                        + readBytes);
148
            }
149
            result = lineSeparator.matches(lastBytes);
150
        }
151 1 1. endsWithNewline : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return result;
152
    }
153
}

Mutations

80

1.1
Location : processFiltered
Killed by : com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest.testWrongFile(com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/NewlineAtEndOfFileCheck::readAndCheckFile → KILLED

83

1.1
Location : processFiltered
Killed by : com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest.testWrongFile(com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/NewlineAtEndOfFileCheck::log → KILLED

116

1.1
Location : readAndCheckFile
Killed by : com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest.testNoNewlineAtEndOfFile(com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest)
negated conditional → KILLED

117

1.1
Location : readAndCheckFile
Killed by : com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest.testNoNewlineAtEndOfFile(com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/NewlineAtEndOfFileCheck::log → KILLED

122

1.1
Location : readAndCheckFile
Killed by : com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest.testCloseRandomAccessFile(com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest)
removed call to com/google/common/io/Closeables::close → KILLED

138

1.1
Location : endsWithNewline
Killed by : com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest.testFileWithEmptyLineOnly(com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest)
changed conditional boundary → KILLED

2.2
Location : endsWithNewline
Killed by : com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest.testNewlineLfAtEndOfFile(com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest)
negated conditional → KILLED

142

1.1
Location : endsWithNewline
Killed by : com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest.testNoNewlineAtEndOfFile(com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest)
Replaced long subtraction with addition → KILLED

2.2
Location : endsWithNewline
Killed by : com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest.testNewlineLfAtEndOfFile(com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest)
removed call to java/io/RandomAccessFile::seek → KILLED

145

1.1
Location : endsWithNewline
Killed by : com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest.testNoNewlineAtEndOfFile(com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheckTest)
negated conditional → KILLED

151

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

Active mutators

Tests examined


Report generated by PIT 1.2.2