New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add rules to suggest usage of check(), require() and error(). #1570
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the rules. They look good to me.
Have you tested them on some of our analysis projects? -> detekt/scripts/get_analysis_projects.groovy
I'm not sure if just checking for the exception thrown is sufficient here.
I have not done it yet, but will definitely do so. Thanks for the tip. Are you worried about false positives or false negatives? I can't really think of any circumstance where it is better to throw an IllegalArgumentException or IllegalStateException directly. But I guess I will see. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's always the chance that someone creates their own version of IllegalStateException or IllegalArgumentException which this will flag because it's not using type or symbol resolution... but I don't think it's worth it to use that for this rule. Looks good!
doSomething() | ||
if (a < 0) throw IllegalStateException() | ||
}""" | ||
Assertions.assertThat(subject.lint(code)).hasSize(1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: please import org.assertj.core.api.Assertions.assertThat
so these can change to assertThat(...)
instead of Assertions.assertThat(...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! That’s a very nice first rule.
The format of the linted code between """ looks very weird.
The plain text has a weird indentation.
Regarding the symbol resolution, I would say we need to go over all rules and see where we can apply it after the PR is merged. |
I just ran a check on most of those analysis projects and there were a lot of occurrences where the rule correctly reports a violation. I did find 2 cases with possible false positives though. Creating a lambda that throws an IllegalArgumentException I would think is an edge case. But I could try to detect this.
This I consider more relevant. Throwing an exception with a cause should never report an issue.
|
This still allows false positives if the exception is created with a cause only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we please resolve the code duplication.
Otherwise, the code and the structure looks very nice now.
@@ -42,6 +42,9 @@ class UseRequire(config: Config = Config.empty) : Rule(config) { | |||
} | |||
|
|||
private fun KtThrowExpression.isIllegalArgumentException(): Boolean { | |||
return findDescendantOfType<KtCallExpression>()?.firstChild?.text == "IllegalArgumentException" | |||
val callExpression = findDescendantOfType<KtCallExpression>() | |||
val argumentCount = callExpression?.valueArgumentList?.children?.size ?: 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code duplication here
Can we group this together and pass the type of the exception?
private fun KtThrowExpression.isIllegalStateException(): Boolean { | ||
return findDescendantOfType<KtCallExpression>()?.firstChild?.text == "IllegalStateException" | ||
private fun KtThrowExpression.isIllegalStateExceptionWithoutCause(): Boolean { | ||
val callExpression = findDescendantOfType<KtCallExpression>() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code duplication here
Can we group this together and pass the type of the exception?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType | ||
import kotlin.reflect.KClass | ||
|
||
internal fun KtThrowExpression.isIllegalStateException() = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice refactoring!
Closes #1502
Since this is my first rule I am glad to get feedback and am open for alternative naming suggestions.