|
29 | 29 | import java.time.Duration; |
30 | 30 | import java.util.*; |
31 | 31 |
|
| 32 | +import static org.openrewrite.java.tree.J.Modifier.Type.*; |
| 33 | + |
32 | 34 | public class UnnecessaryThrows extends Recipe { |
33 | 35 |
|
34 | 36 | @Override |
@@ -136,74 +138,82 @@ private void removeThrownTypes(JavaType.@Nullable Method type) { |
136 | 138 |
|
137 | 139 | return m; |
138 | 140 | } |
139 | | - }; |
140 | | - } |
141 | 141 |
|
| 142 | + private Set<JavaType.FullyQualified> findExceptionCandidates(J.@Nullable MethodDeclaration method) { |
142 | 143 |
|
143 | | - private Set<JavaType.FullyQualified> findExceptionCandidates(J.@Nullable MethodDeclaration method) { |
| 144 | + if (method == null || method.getMethodType() == null || method.isAbstract() || method.isConstructor()) { |
| 145 | + return Collections.emptySet(); |
| 146 | + } |
144 | 147 |
|
145 | | - if (method == null || method.getMethodType() == null || method.isAbstract() || method.isConstructor()) { |
146 | | - return Collections.emptySet(); |
147 | | - } |
| 148 | + // Do not change the API of methods that may be overridden |
| 149 | + if (method.hasModifier(Protected) && !method.hasModifier(Final)) { |
| 150 | + J.ClassDeclaration cd = getCursor().firstEnclosing(J.ClassDeclaration.class); |
| 151 | + if (cd != null && !cd.hasModifier(Final)) { |
| 152 | + return Collections.emptySet(); |
| 153 | + } |
| 154 | + } |
| 155 | + |
| 156 | + //Collect all checked exceptions. |
| 157 | + Set<JavaType.FullyQualified> candidates = new TreeSet<>(Comparator.comparing(JavaType.FullyQualified::getFullyQualifiedName)); |
148 | 158 |
|
149 | | - //Collect all checked exceptions. |
150 | | - Set<JavaType.FullyQualified> candidates = new TreeSet<>(Comparator.comparing(JavaType.FullyQualified::getFullyQualifiedName)); |
| 159 | + if (method.getThrows() != null) { |
| 160 | + for (NameTree exception : method.getThrows()) { |
| 161 | + if (exception.getType() == null || exception.getType() instanceof JavaType.Unknown) { |
| 162 | + return Collections.emptySet(); |
| 163 | + } |
| 164 | + if (exception.getType() instanceof JavaType.FullyQualified && !TypeUtils.isAssignableTo("java.lang.RuntimeException", exception.getType())) { |
| 165 | + candidates.add(TypeUtils.asFullyQualified(exception.getType())); |
| 166 | + } |
| 167 | + } |
| 168 | + } |
151 | 169 |
|
152 | | - if (method.getThrows() != null) { |
153 | | - for (NameTree exception : method.getThrows()) { |
154 | | - if (exception.getType() == null || exception.getType() instanceof JavaType.Unknown) { |
| 170 | + if (candidates.isEmpty()) { |
155 | 171 | return Collections.emptySet(); |
156 | 172 | } |
157 | | - if (exception.getType() instanceof JavaType.FullyQualified && !TypeUtils.isAssignableTo("java.lang.RuntimeException", exception.getType())) { |
158 | | - candidates.add(TypeUtils.asFullyQualified(exception.getType())); |
| 173 | + |
| 174 | + //noinspection ConstantConditions |
| 175 | + if ((method.getMethodType().getDeclaringType() != null && method.getMethodType().getDeclaringType().getFlags().contains(Flag.Final)) || |
| 176 | + method.isAbstract() || method.hasModifier(Static) || |
| 177 | + method.hasModifier(Private) || |
| 178 | + method.hasModifier(Final)) { |
| 179 | + //Consider all checked exceptions as candidates if the type/method are final or the method is private or static. |
| 180 | + return candidates; |
159 | 181 | } |
160 | | - } |
161 | | - } |
162 | | - |
163 | | - if (candidates.isEmpty()) { |
164 | | - return Collections.emptySet(); |
165 | | - } |
166 | | - |
167 | | - //noinspection ConstantConditions |
168 | | - if ((method.getMethodType().getDeclaringType() != null && method.getMethodType().getDeclaringType().getFlags().contains(Flag.Final)) || |
169 | | - method.isAbstract() || method.hasModifier(J.Modifier.Type.Static) || |
170 | | - method.hasModifier(J.Modifier.Type.Private) || |
171 | | - method.hasModifier(J.Modifier.Type.Final)) { |
172 | | - //Consider all checked exceptions as candidates if the type/method are final or the method is private or static. |
173 | | - return candidates; |
174 | | - } |
175 | | - |
176 | | - //Remove any candidates that are defined in an overridden method. |
177 | | - Optional<JavaType.Method> superMethod = TypeUtils.findOverriddenMethod(method.getMethodType()); |
178 | | - if (superMethod.isPresent()) { |
179 | | - JavaType.Method baseMethod = superMethod.get(); |
180 | | - baseMethod.getThrownExceptions(); |
181 | | - for (JavaType baseException : baseMethod.getThrownExceptions()) { |
182 | | - if (baseException instanceof JavaType.FullyQualified) { |
183 | | - candidates.remove(baseException); |
| 182 | + |
| 183 | + //Remove any candidates that are defined in an overridden method. |
| 184 | + Optional<JavaType.Method> superMethod = TypeUtils.findOverriddenMethod(method.getMethodType()); |
| 185 | + if (superMethod.isPresent()) { |
| 186 | + JavaType.Method baseMethod = superMethod.get(); |
| 187 | + baseMethod.getThrownExceptions(); |
| 188 | + for (JavaType baseException : baseMethod.getThrownExceptions()) { |
| 189 | + if (baseException instanceof JavaType.FullyQualified) { |
| 190 | + candidates.remove(baseException); |
| 191 | + } |
| 192 | + } |
184 | 193 | } |
185 | | - } |
186 | | - } |
187 | | - if (!candidates.isEmpty()) { |
188 | | - //Remove any candidates that are defined in Javadocs for the method. |
189 | | - new JavaVisitor<Set<JavaType.FullyQualified>>() { |
190 | | - @Override |
191 | | - protected JavadocVisitor<Set<JavaType.FullyQualified>> getJavadocVisitor() { |
192 | | - return new JavadocVisitor<Set<JavaType.FullyQualified>>(this) { |
| 194 | + if (!candidates.isEmpty()) { |
| 195 | + //Remove any candidates that are defined in Javadocs for the method. |
| 196 | + new JavaVisitor<Set<JavaType.FullyQualified>>() { |
193 | 197 | @Override |
194 | | - public Javadoc visitThrows(Javadoc.Throws aThrows, Set<JavaType.FullyQualified> candidates) { |
195 | | - if (aThrows.getExceptionName() instanceof TypeTree) { |
196 | | - JavaType.FullyQualified exceptionType = TypeUtils.asFullyQualified(((TypeTree) aThrows.getExceptionName()).getType()); |
197 | | - if (exceptionType != null) { |
198 | | - candidates.remove(exceptionType); |
| 198 | + protected JavadocVisitor<Set<JavaType.FullyQualified>> getJavadocVisitor() { |
| 199 | + return new JavadocVisitor<Set<JavaType.FullyQualified>>(this) { |
| 200 | + @Override |
| 201 | + public Javadoc visitThrows(Javadoc.Throws aThrows, Set<JavaType.FullyQualified> candidates) { |
| 202 | + if (aThrows.getExceptionName() instanceof TypeTree) { |
| 203 | + JavaType.FullyQualified exceptionType = TypeUtils.asFullyQualified(((TypeTree) aThrows.getExceptionName()).getType()); |
| 204 | + if (exceptionType != null) { |
| 205 | + candidates.remove(exceptionType); |
| 206 | + } |
| 207 | + } |
| 208 | + return super.visitThrows(aThrows, candidates); |
199 | 209 | } |
200 | | - } |
201 | | - return super.visitThrows(aThrows, candidates); |
| 210 | + }; |
202 | 211 | } |
203 | | - }; |
| 212 | + }.visit(method, candidates); |
204 | 213 | } |
205 | | - }.visit(method, candidates); |
206 | | - } |
207 | | - return candidates; |
| 214 | + return candidates; |
| 215 | + } |
| 216 | + }; |
208 | 217 | } |
| 218 | + |
209 | 219 | } |
0 commit comments