AbstractClassNameCheck.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.naming;
21
22
import java.util.regex.Pattern;
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
 * Ensures that the names of abstract classes conforming to some
32
 * regular expression and check that {@code abstract} modifier exists.
33
 * </p>
34
 * <p>
35
 * Rationale: Abstract classes are convenience base class
36
 * implementations of interfaces, not types as such. As such
37
 * they should be named to indicate this. Also if names of classes
38
 * starts with 'Abstract' it's very convenient that they will
39
 * have abstract modifier.
40
 * </p>
41
 *
42
 * @author <a href="mailto:simon@redhillconsulting.com.au">Simon Harris</a>
43
 * @author <a href="mailto:solid.danil@gmail.com">Danil Lopatin</a>
44
 */
45
@StatelessCheck
46
public final class AbstractClassNameCheck extends AbstractCheck {
47
48
    /**
49
     * A key is pointing to the warning message text in "messages.properties"
50
     * file.
51
     */
52
    public static final String MSG_ILLEGAL_ABSTRACT_CLASS_NAME = "illegal.abstract.class.name";
53
54
    /**
55
     * A key is pointing to the warning message text in "messages.properties"
56
     * file.
57
     */
58
    public static final String MSG_NO_ABSTRACT_CLASS_MODIFIER = "no.abstract.class.modifier";
59
60
    /** Whether to ignore checking the modifier. */
61
    private boolean ignoreModifier;
62
63
    /** Whether to ignore checking the name. */
64
    private boolean ignoreName;
65
66
    /** The regexp to match against. */
67
    private Pattern format = Pattern.compile("^Abstract.+$");
68
69
    /**
70
     * Whether to ignore checking for the {@code abstract} modifier.
71
     * @param value new value
72
     */
73
    public void setIgnoreModifier(boolean value) {
74
        ignoreModifier = value;
75
    }
76
77
    /**
78
     * Whether to ignore checking the name.
79
     * @param value new value.
80
     */
81
    public void setIgnoreName(boolean value) {
82
        ignoreName = value;
83
    }
84
85
    /**
86
     * Set the format for the specified regular expression.
87
     * @param pattern the new pattern
88
     */
89
    public void setFormat(Pattern pattern) {
90
        format = pattern;
91
    }
92
93
    @Override
94
    public int[] getDefaultTokens() {
95 1 1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/naming/AbstractClassNameCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return getRequiredTokens();
96
    }
97
98
    @Override
99
    public int[] getRequiredTokens() {
100 1 1. getRequiredTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/naming/AbstractClassNameCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return new int[] {TokenTypes.CLASS_DEF};
101
    }
102
103
    @Override
104
    public int[] getAcceptableTokens() {
105 1 1. getAcceptableTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/naming/AbstractClassNameCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return getRequiredTokens();
106
    }
107
108
    @Override
109
    public void visitToken(DetailAST ast) {
110 1 1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/naming/AbstractClassNameCheck::visitClassDef → KILLED
        visitClassDef(ast);
111
    }
112
113
    /**
114
     * Checks class definition.
115
     * @param ast class definition for check.
116
     */
117
    private void visitClassDef(DetailAST ast) {
118
        final String className =
119
            ast.findFirstToken(TokenTypes.IDENT).getText();
120 1 1. visitClassDef : negated conditional → KILLED
        if (isAbstract(ast)) {
121
            // if class has abstract modifier
122 2 1. visitClassDef : negated conditional → KILLED
2. visitClassDef : negated conditional → KILLED
            if (!ignoreName && !isMatchingClassName(className)) {
123 1 1. visitClassDef : removed call to com/puppycrawl/tools/checkstyle/checks/naming/AbstractClassNameCheck::log → KILLED
                log(ast.getLineNo(), ast.getColumnNo(),
124
                    MSG_ILLEGAL_ABSTRACT_CLASS_NAME, className, format.pattern());
125
            }
126
        }
127 2 1. visitClassDef : negated conditional → KILLED
2. visitClassDef : negated conditional → KILLED
        else if (!ignoreModifier && isMatchingClassName(className)) {
128 1 1. visitClassDef : removed call to com/puppycrawl/tools/checkstyle/checks/naming/AbstractClassNameCheck::log → KILLED
            log(ast.getLineNo(), ast.getColumnNo(),
129
                MSG_NO_ABSTRACT_CLASS_MODIFIER, className);
130
        }
131
    }
132
133
    /**
134
     * Checks if declared class is abstract or not.
135
     * @param ast class definition for check.
136
     * @return true if a given class declared as abstract.
137
     */
138
    private static boolean isAbstract(DetailAST ast) {
139
        final DetailAST abstractAST = ast.findFirstToken(TokenTypes.MODIFIERS)
140
            .findFirstToken(TokenTypes.ABSTRACT);
141
142 2 1. isAbstract : negated conditional → KILLED
2. isAbstract : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return abstractAST != null;
143
    }
144
145
    /**
146
     * Returns true if class name matches format of abstract class names.
147
     * @param className class name for check.
148
     * @return true if class name matches format of abstract class names.
149
     */
150
    private boolean isMatchingClassName(String className) {
151 1 1. isMatchingClassName : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return format.matcher(className).find();
152
    }
153
154
}

Mutations

95

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

100

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

105

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

110

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest.testFalsePositive(com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/naming/AbstractClassNameCheck::visitClassDef → KILLED

120

1.1
Location : visitClassDef
Killed by : com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest.testFalsePositive(com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest)
negated conditional → KILLED

122

1.1
Location : visitClassDef
Killed by : com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest.testIllegalClassType(com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest)
negated conditional → KILLED

2.2
Location : visitClassDef
Killed by : com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest.testCustomFormat(com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest)
negated conditional → KILLED

123

1.1
Location : visitClassDef
Killed by : com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest.testCustomFormat(com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/naming/AbstractClassNameCheck::log → KILLED

127

1.1
Location : visitClassDef
Killed by : com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest.testFalsePositive(com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest)
negated conditional → KILLED

2.2
Location : visitClassDef
Killed by : com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest.testFalsePositive(com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest)
negated conditional → KILLED

128

1.1
Location : visitClassDef
Killed by : com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest.testFalsePositive(com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/naming/AbstractClassNameCheck::log → KILLED

142

1.1
Location : isAbstract
Killed by : com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest.testFalsePositive(com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest)
negated conditional → KILLED

2.2
Location : isAbstract
Killed by : com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest.testFalsePositive(com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest)
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

151

1.1
Location : isMatchingClassName
Killed by : com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest.testFalsePositive(com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest)
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

Active mutators

Tests examined


Report generated by PIT 1.3.1