DefaultComesLastCheck.java

1
////////////////////////////////////////////////////////////////////////////////
2
// checkstyle: Checks Java source code for adherence to a set of rules.
3
// Copyright (C) 2001-2018 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.coding;
21
22
import java.util.Objects;
23
24
import com.puppycrawl.tools.checkstyle.StatelessCheck;
25
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
26
import com.puppycrawl.tools.checkstyle.api.DetailAST;
27
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
28
29
/**
30
 * <p>
31
 * Check that the {@code default} is after all the {@code case}s
32
 * in a {@code switch} statement.
33
 * </p>
34
 * <p>
35
 * Rationale: Java allows {@code default} anywhere within the
36
 * {@code switch} statement. But if it comes after the last
37
 * {@code case} then it is more readable.
38
 * </p>
39
 * <p>
40
 * An example of how to configure the check is:
41
 * </p>
42
 * <pre>
43
 * &lt;module name="DefaultComesLast"/&gt;
44
 * </pre>
45
 * @author o_sukhodolsky
46
 */
47
@StatelessCheck
48
public class DefaultComesLastCheck extends AbstractCheck {
49
50
    /**
51
     * A key is pointing to the warning message text in "messages.properties"
52
     * file.
53
     */
54
    public static final String MSG_KEY = "default.comes.last";
55
56
    /**
57
     * A key is pointing to the warning message text in "messages.properties"
58
     * file.
59
     */
60
    public static final String MSG_KEY_SKIP_IF_LAST_AND_SHARED_WITH_CASE =
61
            "default.comes.last.in.casegroup";
62
63
    /** Whether to process skipIfLastAndSharedWithCaseInSwitch() invocations. */
64
    private boolean skipIfLastAndSharedWithCase;
65
66
    @Override
67
    public int[] getAcceptableTokens() {
68 1 1. getAcceptableTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/DefaultComesLastCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return getRequiredTokens();
69
    }
70
71
    @Override
72
    public int[] getDefaultTokens() {
73 1 1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/DefaultComesLastCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return getRequiredTokens();
74
    }
75
76
    @Override
77
    public int[] getRequiredTokens() {
78 1 1. getRequiredTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/DefaultComesLastCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return new int[] {
79
            TokenTypes.LITERAL_DEFAULT,
80
        };
81
    }
82
83
    /**
84
     * Whether to allow default keyword not in last but surrounded with case.
85
     * @param newValue whether to ignore checking.
86
     */
87
    public void setSkipIfLastAndSharedWithCase(boolean newValue) {
88
        skipIfLastAndSharedWithCase = newValue;
89
    }
90
91
    @Override
92
    public void visitToken(DetailAST ast) {
93
        final DetailAST defaultGroupAST = ast.getParent();
94
        //default keywords used in annotations too - not what we're
95
        //interested in
96 1 1. visitToken : negated conditional → KILLED
        if (defaultGroupAST.getType() != TokenTypes.ANNOTATION_FIELD_DEF
97 1 1. visitToken : negated conditional → KILLED
                && defaultGroupAST.getType() != TokenTypes.MODIFIERS) {
98 1 1. visitToken : negated conditional → KILLED
            if (skipIfLastAndSharedWithCase) {
99 1 1. visitToken : negated conditional → KILLED
                if (Objects.nonNull(findNextSibling(ast, TokenTypes.LITERAL_CASE))) {
100 1 1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/coding/DefaultComesLastCheck::log → KILLED
                    log(ast, MSG_KEY_SKIP_IF_LAST_AND_SHARED_WITH_CASE);
101
                }
102 1 1. visitToken : negated conditional → KILLED
                else if (ast.getPreviousSibling() == null
103 1 1. visitToken : negated conditional → KILLED
                    && Objects.nonNull(findNextSibling(defaultGroupAST,
104
                                                       TokenTypes.CASE_GROUP))) {
105 1 1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/coding/DefaultComesLastCheck::log → KILLED
                    log(ast, MSG_KEY);
106
                }
107
            }
108 1 1. visitToken : negated conditional → KILLED
            else if (Objects.nonNull(findNextSibling(defaultGroupAST,
109
                                                     TokenTypes.CASE_GROUP))) {
110 1 1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/coding/DefaultComesLastCheck::log → KILLED
                log(ast, MSG_KEY);
111
            }
112
        }
113
    }
114
115
    /**
116
     * Return token type only if passed tokenType in argument is found or returns -1.
117
     *
118
     * @param ast root node.
119
     * @param tokenType tokentype to be processed.
120
     * @return token if desired token is found or else null.
121
     */
122
    private static DetailAST findNextSibling(DetailAST ast, int tokenType) {
123
        DetailAST token = null;
124
        DetailAST node = ast.getNextSibling();
125 1 1. findNextSibling : negated conditional → KILLED
        while (node != null) {
126 1 1. findNextSibling : negated conditional → KILLED
            if (node.getType() == tokenType) {
127
                token = node;
128
                break;
129
            }
130
            node = node.getNextSibling();
131
        }
132 1 1. findNextSibling : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/DefaultComesLastCheck::findNextSibling to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return token;
133
    }
134
135
}

Mutations

68

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

73

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

78

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

96

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

97

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

98

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

99

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest.testSkipIfLastAndSharedWithCase(com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest)
negated conditional → KILLED

100

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest.testSkipIfLastAndSharedWithCase(com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/coding/DefaultComesLastCheck::log → KILLED

102

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest.testSkipIfLastAndSharedWithCase(com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest)
negated conditional → KILLED

103

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest.testSkipIfLastAndSharedWithCase(com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest)
negated conditional → KILLED

105

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest.testSkipIfLastAndSharedWithCase(com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/coding/DefaultComesLastCheck::log → KILLED

108

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

110

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/coding/DefaultComesLastCheck::log → KILLED

125

1.1
Location : findNextSibling
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest)
negated conditional → KILLED

126

1.1
Location : findNextSibling
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.DefaultComesLastCheckTest)
negated conditional → KILLED

132

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

Active mutators

Tests examined


Report generated by PIT 1.3.1