OperatorWrapCheck.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.whitespace;
21
22
import java.util.Locale;
23
24
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
25
import com.puppycrawl.tools.checkstyle.api.DetailAST;
26
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
27
import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
28
29
/**
30
 * <p>
31
 * Checks line wrapping for operators.
32
 * The policy to verify is specified using the {@link WrapOption} class
33
 * and defaults to {@link WrapOption#NL}.
34
 * </p>
35
 * <p> By default the check will check the following operators:
36
 *  {@link TokenTypes#BAND BAND},
37
 *  {@link TokenTypes#BOR BOR},
38
 *  {@link TokenTypes#BSR BSR},
39
 *  {@link TokenTypes#BXOR BXOR},
40
 *  {@link TokenTypes#COLON COLON},
41
 *  {@link TokenTypes#DIV DIV},
42
 *  {@link TokenTypes#EQUAL EQUAL},
43
 *  {@link TokenTypes#GE GE},
44
 *  {@link TokenTypes#GT GT},
45
 *  {@link TokenTypes#LAND LAND},
46
 *  {@link TokenTypes#LE LE},
47
 *  {@link TokenTypes#LITERAL_INSTANCEOF LITERAL_INSTANCEOF},
48
 *  {@link TokenTypes#LOR LOR},
49
 *  {@link TokenTypes#LT LT},
50
 *  {@link TokenTypes#MINUS MINUS},
51
 *  {@link TokenTypes#MOD MOD},
52
 *  {@link TokenTypes#NOT_EQUAL NOT_EQUAL},
53
 *  {@link TokenTypes#PLUS PLUS},
54
 *  {@link TokenTypes#QUESTION QUESTION},
55
 *  {@link TokenTypes#SL SL},
56
 *  {@link TokenTypes#SR SR},
57
 *  {@link TokenTypes#STAR STAR}.
58
 * Other acceptable tokens are
59
 *  {@link TokenTypes#ASSIGN ASSIGN},
60
 *  {@link TokenTypes#BAND_ASSIGN BAND_ASSIGN},
61
 *  {@link TokenTypes#BOR_ASSIGN BOR_ASSIGN},
62
 *  {@link TokenTypes#BSR_ASSIGN BSR_ASSIGN},
63
 *  {@link TokenTypes#BXOR_ASSIGN BXOR_ASSIGN},
64
 *  {@link TokenTypes#DIV_ASSIGN DIV_ASSIGN},
65
 *  {@link TokenTypes#MINUS_ASSIGN MINUS_ASSIGN},
66
 *  {@link TokenTypes#MOD_ASSIGN MOD_ASSIGN},
67
 *  {@link TokenTypes#PLUS_ASSIGN PLUS_ASSIGN},
68
 *  {@link TokenTypes#SL_ASSIGN SL_ASSIGN},
69
 *  {@link TokenTypes#SR_ASSIGN SR_ASSIGN},
70
 *  {@link TokenTypes#STAR_ASSIGN STAR_ASSIGN}.
71
 *  {@link TokenTypes#METHOD_REF METHOD_REF}.
72
 * </p>
73
 *  <p>
74
 * An example of how to configure the check is:
75
 * </p>
76
 * <pre>
77
 * &lt;module name="OperatorWrap"/&gt;
78
 * </pre>
79
 * <p> An example of how to configure the check for assignment operators at the
80
 * end of a line is:
81
 * </p>
82
 * <pre>
83
 * &lt;module name="OperatorWrap"&gt;
84
 *     &lt;property name="tokens"
85
 *               value="ASSIGN,DIV_ASSIGN,PLUS_ASSIGN,MINUS_ASSIGN,STAR_ASSIGN,MOD_ASSIGN
86
 *               ,SR_ASSIGN,BSR_ASSIGN,SL_ASSIGN,BXOR_ASSIGN,BOR_ASSIGN,BAND_ASSIGN"/&gt;
87
 *     &lt;property name="option" value="eol"/&gt;
88
 * &lt;/module&gt;
89
 * </pre>
90
 *
91
 * @author Rick Giles
92
 */
93
public class OperatorWrapCheck
94
    extends AbstractCheck {
95
96
    /**
97
     * A key is pointing to the warning message text in "messages.properties"
98
     * file.
99
     */
100
    public static final String MSG_LINE_NEW = "line.new";
101
102
    /**
103
     * A key is pointing to the warning message text in "messages.properties"
104
     * file.
105
     */
106
    public static final String MSG_LINE_PREVIOUS = "line.previous";
107
108
    /** The policy to enforce. */
109
    private WrapOption option = WrapOption.NL;
110
111
    /**
112
     * Set the option to enforce.
113
     * @param optionStr string to decode option from
114
     * @throws IllegalArgumentException if unable to decode
115
     */
116
    public void setOption(String optionStr) {
117
        try {
118
            option = WrapOption.valueOf(optionStr.trim().toUpperCase(Locale.ENGLISH));
119
        }
120
        catch (IllegalArgumentException iae) {
121
            throw new IllegalArgumentException("unable to parse " + optionStr, iae);
122
        }
123
    }
124
125
    @Override
126
    public int[] getDefaultTokens() {
127 1 1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/whitespace/OperatorWrapCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return new int[] {
128
            TokenTypes.QUESTION,          // '?'
129
            TokenTypes.COLON,             // ':' (not reported for a case)
130
            TokenTypes.EQUAL,             // "=="
131
            TokenTypes.NOT_EQUAL,         // "!="
132
            TokenTypes.DIV,               // '/'
133
            TokenTypes.PLUS,              //' +' (unary plus is UNARY_PLUS)
134
            TokenTypes.MINUS,             // '-' (unary minus is UNARY_MINUS)
135
            TokenTypes.STAR,              // '*'
136
            TokenTypes.MOD,               // '%'
137
            TokenTypes.SR,                // ">>"
138
            TokenTypes.BSR,               // ">>>"
139
            TokenTypes.GE,                // ">="
140
            TokenTypes.GT,                // ">"
141
            TokenTypes.SL,                // "<<"
142
            TokenTypes.LE,                // "<="
143
            TokenTypes.LT,                // '<'
144
            TokenTypes.BXOR,              // '^'
145
            TokenTypes.BOR,               // '|'
146
            TokenTypes.LOR,               // "||"
147
            TokenTypes.BAND,              // '&'
148
            TokenTypes.LAND,              // "&&"
149
            TokenTypes.TYPE_EXTENSION_AND,
150
            TokenTypes.LITERAL_INSTANCEOF,
151
        };
152
    }
153
154
    @Override
155
    public int[] getAcceptableTokens() {
156 1 1. getAcceptableTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/whitespace/OperatorWrapCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return new int[] {
157
            TokenTypes.QUESTION,          // '?'
158
            TokenTypes.COLON,             // ':' (not reported for a case)
159
            TokenTypes.EQUAL,             // "=="
160
            TokenTypes.NOT_EQUAL,         // "!="
161
            TokenTypes.DIV,               // '/'
162
            TokenTypes.PLUS,              //' +' (unary plus is UNARY_PLUS)
163
            TokenTypes.MINUS,             // '-' (unary minus is UNARY_MINUS)
164
            TokenTypes.STAR,              // '*'
165
            TokenTypes.MOD,               // '%'
166
            TokenTypes.SR,                // ">>"
167
            TokenTypes.BSR,               // ">>>"
168
            TokenTypes.GE,                // ">="
169
            TokenTypes.GT,                // ">"
170
            TokenTypes.SL,                // "<<"
171
            TokenTypes.LE,                // "<="
172
            TokenTypes.LT,                // '<'
173
            TokenTypes.BXOR,              // '^'
174
            TokenTypes.BOR,               // '|'
175
            TokenTypes.LOR,               // "||"
176
            TokenTypes.BAND,              // '&'
177
            TokenTypes.LAND,              // "&&"
178
            TokenTypes.LITERAL_INSTANCEOF,
179
            TokenTypes.TYPE_EXTENSION_AND,
180
            TokenTypes.ASSIGN,            // '='
181
            TokenTypes.DIV_ASSIGN,        // "/="
182
            TokenTypes.PLUS_ASSIGN,       // "+="
183
            TokenTypes.MINUS_ASSIGN,      //"-="
184
            TokenTypes.STAR_ASSIGN,       // "*="
185
            TokenTypes.MOD_ASSIGN,        // "%="
186
            TokenTypes.SR_ASSIGN,         // ">>="
187
            TokenTypes.BSR_ASSIGN,        // ">>>="
188
            TokenTypes.SL_ASSIGN,         // "<<="
189
            TokenTypes.BXOR_ASSIGN,       // "^="
190
            TokenTypes.BOR_ASSIGN,        // "|="
191
            TokenTypes.BAND_ASSIGN,       // "&="
192
            TokenTypes.METHOD_REF,        // "::"
193
194
        };
195
    }
196
197
    @Override
198
    public int[] getRequiredTokens() {
199 1 1. getRequiredTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/whitespace/OperatorWrapCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return CommonUtils.EMPTY_INT_ARRAY;
200
    }
201
202
    @Override
203
    public void visitToken(DetailAST ast) {
204
        final DetailAST parent = ast.getParent();
205
        //we do not want to check colon for cases and defaults
206 1 1. visitToken : negated conditional → KILLED
        if (ast.getType() != TokenTypes.COLON
207 1 1. visitToken : negated conditional → KILLED
                || parent.getType() != TokenTypes.LITERAL_DEFAULT
208 1 1. visitToken : negated conditional → KILLED
                    && parent.getType() != TokenTypes.LITERAL_CASE) {
209
            final String text = ast.getText();
210
            final int colNo = ast.getColumnNo();
211
            final int lineNo = ast.getLineNo();
212 1 1. visitToken : Replaced integer subtraction with addition → KILLED
            final String currentLine = getLine(lineNo - 1);
213
214
            // Check if rest of line is whitespace, and not just the operator
215
            // by itself. This last bit is to handle the operator on a line by
216
            // itself.
217 1 1. visitToken : negated conditional → KILLED
            if (option == WrapOption.NL
218 1 1. visitToken : negated conditional → KILLED
                    && !text.equals(currentLine.trim())
219 2 1. visitToken : Replaced integer addition with subtraction → KILLED
2. visitToken : negated conditional → KILLED
                    && CommonUtils.isBlank(currentLine.substring(colNo + text.length()))) {
220 1 1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/whitespace/OperatorWrapCheck::log → KILLED
                log(lineNo, colNo, MSG_LINE_NEW, text);
221
            }
222 2 1. visitToken : Replaced integer subtraction with addition → KILLED
2. visitToken : negated conditional → KILLED
            else if (option == WrapOption.EOL
223 1 1. visitToken : negated conditional → KILLED
                    && CommonUtils.hasWhitespaceBefore(colNo - 1, currentLine)) {
224 1 1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/whitespace/OperatorWrapCheck::log → KILLED
                log(lineNo, colNo, MSG_LINE_PREVIOUS, text);
225
            }
226
        }
227
    }
228
}

Mutations

127

1.1
Location : getDefaultTokens
Killed by : com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest)
mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/whitespace/OperatorWrapCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED

156

1.1
Location : getAcceptableTokens
Killed by : com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest.testNonDefOpsDefault(com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest)
mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/whitespace/OperatorWrapCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED

199

1.1
Location : getRequiredTokens
Killed by : com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest.testNonDefOpsDefault(com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest)
mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/whitespace/OperatorWrapCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED

206

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest)
negated conditional → KILLED

207

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest)
negated conditional → KILLED

208

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest)
negated conditional → KILLED

212

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest.testNonDefOpsDefault(com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest)
Replaced integer subtraction with addition → KILLED

217

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest.testNonDefOpsDefault(com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest)
negated conditional → KILLED

218

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest.testNonDefOpsDefault(com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest)
negated conditional → KILLED

219

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest.testNonDefOpsDefault(com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest)
Replaced integer addition with subtraction → KILLED

2.2
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest.testNonDefOpsDefault(com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest)
negated conditional → KILLED

220

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest.testNonDefOpsDefault(com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/whitespace/OperatorWrapCheck::log → KILLED

222

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest.testNonDefOpsWrapEol(com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest)
Replaced integer subtraction with addition → KILLED

2.2
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest.testNonDefOpsDefault(com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest)
negated conditional → KILLED

223

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest.testNonDefOpsWrapEol(com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest)
negated conditional → KILLED

224

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest.testNonDefOpsWrapEol(com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/whitespace/OperatorWrapCheck::log → KILLED

Active mutators

Tests examined


Report generated by PIT 1.2.2