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.imports; | |
21 | ||
22 | import java.util.ArrayList; | |
23 | import java.util.List; | |
24 | import java.util.regex.Pattern; | |
25 | ||
26 | import com.puppycrawl.tools.checkstyle.api.AbstractCheck; | |
27 | import com.puppycrawl.tools.checkstyle.api.DetailAST; | |
28 | import com.puppycrawl.tools.checkstyle.api.FullIdent; | |
29 | import com.puppycrawl.tools.checkstyle.api.TokenTypes; | |
30 | import com.puppycrawl.tools.checkstyle.utils.CommonUtils; | |
31 | ||
32 | /** | |
33 | * <p> | |
34 | * Checks for imports from a set of illegal packages. | |
35 | * By default, the check rejects all {@code sun.*} packages | |
36 | * since programs that contain direct calls to the {@code sun.*} packages | |
37 | * are <a href="http://www.oracle.com/technetwork/java/faq-sun-packages-142232.html"> | |
38 | * not 100% Pure Java</a>. | |
39 | * </p> | |
40 | * <p> | |
41 | * To reject other packages, set property illegalPkgs to a comma-separated | |
42 | * list of the illegal packages. | |
43 | * </p> | |
44 | * <p> | |
45 | * An example of how to configure the check is: | |
46 | * </p> | |
47 | * <pre> | |
48 | * <module name="IllegalImport"/> | |
49 | * </pre> | |
50 | * <p> | |
51 | * An example of how to configure the check so that it rejects packages | |
52 | * {@code java.io.*} and {@code java.sql.*} is | |
53 | * </p> | |
54 | * <pre> | |
55 | * <module name="IllegalImport"> | |
56 | * <property name="illegalPkgs" value="java.io, java.sql"/> | |
57 | * </module> | |
58 | * | |
59 | * Compatible with Java 1.5 source. | |
60 | * | |
61 | * </pre> | |
62 | * @author Oliver Burn | |
63 | * @author Lars Kühne | |
64 | */ | |
65 | public class IllegalImportCheck | |
66 | extends AbstractCheck { | |
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 = "import.illegal"; | |
73 | ||
74 | /** The compiled regular expressions for packages. */ | |
75 | private final List<Pattern> illegalPkgsRegexps = new ArrayList<>(); | |
76 | ||
77 | /** The compiled regular expressions for classes. */ | |
78 | private final List<Pattern> illegalClassesRegexps = new ArrayList<>(); | |
79 | ||
80 | /** List of illegal packages. */ | |
81 | private String[] illegalPkgs; | |
82 | ||
83 | /** List of illegal classes. */ | |
84 | private String[] illegalClasses; | |
85 | ||
86 | /** | |
87 | * Whether the packages or class names | |
88 | * should be interpreted as regular expressions. | |
89 | */ | |
90 | private boolean regexp; | |
91 | ||
92 | /** | |
93 | * Creates a new {@code IllegalImportCheck} instance. | |
94 | */ | |
95 | public IllegalImportCheck() { | |
96 |
1
1. |
setIllegalPkgs("sun"); |
97 | } | |
98 | ||
99 | /** | |
100 | * Set the list of illegal packages. | |
101 | * @param from array of illegal packages | |
102 | * @noinspection WeakerAccess | |
103 | */ | |
104 | public final void setIllegalPkgs(String... from) { | |
105 | illegalPkgs = from.clone(); | |
106 |
1
1. setIllegalPkgs : removed call to java/util/List::clear → KILLED |
illegalPkgsRegexps.clear(); |
107 |
3
1. setIllegalPkgs : changed conditional boundary → KILLED 2. setIllegalPkgs : Changed increment from 1 to -1 → KILLED 3. setIllegalPkgs : negated conditional → KILLED |
for (String illegalPkg : illegalPkgs) { |
108 | illegalPkgsRegexps.add(CommonUtils.createPattern("^" + illegalPkg + "\\..*")); | |
109 | } | |
110 | } | |
111 | ||
112 | /** | |
113 | * Set the list of illegal classes. | |
114 | * @param from array of illegal classes | |
115 | */ | |
116 | public void setIllegalClasses(String... from) { | |
117 | illegalClasses = from.clone(); | |
118 |
3
1. setIllegalClasses : changed conditional boundary → KILLED 2. setIllegalClasses : Changed increment from 1 to -1 → KILLED 3. setIllegalClasses : negated conditional → KILLED |
for (String illegalClass : illegalClasses) { |
119 | illegalClassesRegexps.add(CommonUtils.createPattern(illegalClass)); | |
120 | } | |
121 | } | |
122 | ||
123 | /** | |
124 | * Controls whether the packages or class names | |
125 | * should be interpreted as regular expressions. | |
126 | * @param regexp a {@code Boolean} value | |
127 | */ | |
128 | public void setRegexp(boolean regexp) { | |
129 | this.regexp = regexp; | |
130 | } | |
131 | ||
132 | @Override | |
133 | public int[] getDefaultTokens() { | |
134 |
1
1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/IllegalImportCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return getAcceptableTokens(); |
135 | } | |
136 | ||
137 | @Override | |
138 | public int[] getAcceptableTokens() { | |
139 |
1
1. getAcceptableTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/IllegalImportCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return new int[] {TokenTypes.IMPORT, TokenTypes.STATIC_IMPORT}; |
140 | } | |
141 | ||
142 | @Override | |
143 | public int[] getRequiredTokens() { | |
144 |
1
1. getRequiredTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/IllegalImportCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return getAcceptableTokens(); |
145 | } | |
146 | ||
147 | @Override | |
148 | public void visitToken(DetailAST ast) { | |
149 | final FullIdent imp; | |
150 |
1
1. visitToken : negated conditional → KILLED |
if (ast.getType() == TokenTypes.IMPORT) { |
151 | imp = FullIdent.createFullIdentBelow(ast); | |
152 | } | |
153 | else { | |
154 | imp = FullIdent.createFullIdent( | |
155 | ast.getFirstChild().getNextSibling()); | |
156 | } | |
157 |
1
1. visitToken : negated conditional → KILLED |
if (isIllegalImport(imp.getText())) { |
158 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/imports/IllegalImportCheck::log → KILLED |
log(ast.getLineNo(), |
159 | ast.getColumnNo(), | |
160 | MSG_KEY, | |
161 | imp.getText()); | |
162 | } | |
163 | } | |
164 | ||
165 | /** | |
166 | * Checks if an import matches one of the regular expressions | |
167 | * for illegal packages or illegal class names. | |
168 | * @param importText the argument of the import keyword | |
169 | * @return if {@code importText} matches one of the regular expressions | |
170 | * for illegal packages or illegal class names | |
171 | */ | |
172 | private boolean isIllegalImportByRegularExpressions(String importText) { | |
173 | boolean result = false; | |
174 |
1
1. isIllegalImportByRegularExpressions : negated conditional → KILLED |
for (Pattern pattern : illegalPkgsRegexps) { |
175 |
1
1. isIllegalImportByRegularExpressions : negated conditional → KILLED |
if (pattern.matcher(importText).matches()) { |
176 | result = true; | |
177 | break; | |
178 | } | |
179 | } | |
180 |
1
1. isIllegalImportByRegularExpressions : negated conditional → KILLED |
if (!result) { |
181 |
1
1. isIllegalImportByRegularExpressions : negated conditional → KILLED |
for (Pattern pattern : illegalClassesRegexps) { |
182 |
1
1. isIllegalImportByRegularExpressions : negated conditional → KILLED |
if (pattern.matcher(importText).matches()) { |
183 | result = true; | |
184 | break; | |
185 | } | |
186 | } | |
187 | } | |
188 |
1
1. isIllegalImportByRegularExpressions : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return result; |
189 | } | |
190 | ||
191 | /** | |
192 | * Checks if an import is from a package or class name that must not be used. | |
193 | * @param importText the argument of the import keyword | |
194 | * @return if {@code importText} contains an illegal package prefix or equals illegal class name | |
195 | */ | |
196 | private boolean isIllegalImportByPackagesAndClassNames(String importText) { | |
197 | boolean result = false; | |
198 |
3
1. isIllegalImportByPackagesAndClassNames : changed conditional boundary → KILLED 2. isIllegalImportByPackagesAndClassNames : Changed increment from 1 to -1 → KILLED 3. isIllegalImportByPackagesAndClassNames : negated conditional → KILLED |
for (String element : illegalPkgs) { |
199 |
1
1. isIllegalImportByPackagesAndClassNames : negated conditional → KILLED |
if (importText.startsWith(element + ".")) { |
200 | result = true; | |
201 | break; | |
202 | } | |
203 | } | |
204 |
2
1. isIllegalImportByPackagesAndClassNames : negated conditional → KILLED 2. isIllegalImportByPackagesAndClassNames : negated conditional → KILLED |
if (!result && illegalClasses != null) { |
205 |
3
1. isIllegalImportByPackagesAndClassNames : changed conditional boundary → KILLED 2. isIllegalImportByPackagesAndClassNames : Changed increment from 1 to -1 → KILLED 3. isIllegalImportByPackagesAndClassNames : negated conditional → KILLED |
for (String element : illegalClasses) { |
206 |
1
1. isIllegalImportByPackagesAndClassNames : negated conditional → KILLED |
if (importText.equals(element)) { |
207 | result = true; | |
208 | break; | |
209 | } | |
210 | } | |
211 | } | |
212 |
1
1. isIllegalImportByPackagesAndClassNames : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return result; |
213 | } | |
214 | ||
215 | /** | |
216 | * Checks if an import is from a package or class name that must not be used. | |
217 | * @param importText the argument of the import keyword | |
218 | * @return if {@code importText} is illegal import | |
219 | */ | |
220 | private boolean isIllegalImport(String importText) { | |
221 | final boolean result; | |
222 |
1
1. isIllegalImport : negated conditional → KILLED |
if (regexp) { |
223 | result = isIllegalImportByRegularExpressions(importText); | |
224 | } | |
225 | else { | |
226 | result = isIllegalImportByPackagesAndClassNames(importText); | |
227 | } | |
228 |
1
1. isIllegalImport : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return result; |
229 | } | |
230 | } | |
Mutations | ||
96 |
1.1 |
|
106 |
1.1 |
|
107 |
1.1 2.2 3.3 |
|
118 |
1.1 2.2 3.3 |
|
134 |
1.1 |
|
139 |
1.1 |
|
144 |
1.1 |
|
150 |
1.1 |
|
157 |
1.1 |
|
158 |
1.1 |
|
174 |
1.1 |
|
175 |
1.1 |
|
180 |
1.1 |
|
181 |
1.1 |
|
182 |
1.1 |
|
188 |
1.1 |
|
198 |
1.1 2.2 3.3 |
|
199 |
1.1 |
|
204 |
1.1 2.2 |
|
205 |
1.1 2.2 3.3 |
|
206 |
1.1 |
|
212 |
1.1 |
|
222 |
1.1 |
|
228 |
1.1 |