Skip to content

Instantly share code, notes, and snippets.

@alistairsykes
Last active November 4, 2019 08:22
Show Gist options
  • Save alistairsykes/4de535d668d8fb25f660295348d4e440 to your computer and use it in GitHub Desktop.
Save alistairsykes/4de535d668d8fb25f660295348d4e440 to your computer and use it in GitHub Desktop.
import com.pinterest.ktlint.core.Rule
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.KtNodeTypes.CALL_EXPRESSION
import org.jetbrains.kotlin.com.intellij.lang.ASTNode
import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.CompositeElement
import org.jetbrains.kotlin.com.intellij.psi.tree.TokenSet
import package.Utils
class NamedParametersRule(private val shouldError: Boolean = false) : Rule(RULE_ID) {
companion object {
const val RULE_ID = "named-parameters"
const val NAMED_PARAMS_LIMIT = 2
private val listIgnoreCases = listOf(
"listof",
"setof",
"mapof",
"arrayof",
"allof"
)
private val specialIgnoreCases = listOf(
"Triple",
"Pair",
"invoke",
"compareBy"
)
private val javaNoiseReduceCases = listOf(
"ActivityTestRule",
"inflate",
"makeText",
"getString",
"applyDimension",
"setCompoundDrawablesRelativeWithIntrinsicBounds",
"getQuantityString",
"onActivityResult",
"perform",
"setSpan",
"setPaddingRelative",
"setPadding"
)
}
override fun visit(
node: ASTNode,
autoCorrect: Boolean,
emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit
) {
if (autoCorrect) return
if (node is CompositeElement && node.elementType == CALL_EXPRESSION) {
val expression = node
.getChildren(TokenSet.create(KtNodeTypes.REFERENCE_EXPRESSION))
.firstOrNull()
val callText = expression?.text
for (listIgnoreCase in listIgnoreCases) {
if (callText?.contains(listIgnoreCase, true) == true) return
}
if (callText in specialIgnoreCases) return
if (callText in javaNoiseReduceCases) return
val argumentList = node.getChildren(TokenSet.create(KtNodeTypes.VALUE_ARGUMENT_LIST))
val arguments = argumentList
.singleOrNull()
?.getChildren(TokenSet.create(KtNodeTypes.VALUE_ARGUMENT))
?: return
if (arguments.size > NAMED_PARAMS_LIMIT) {
if (arguments.all { it.text.contains(Regex("any(.*?)\\(\\)")) }) return
val error = arguments.any {
it.getChildren(TokenSet.create(KtNodeTypes.VALUE_ARGUMENT_NAME)).isEmpty()
}
if (error) {
val errorMessage = "Named parameters: ${node.text}"
if (shouldError) {
emit(
node.startOffset,
"Error - $errorMessage",
false
)
} else {
val clazz = Utils.getOuterClass(node)
if (clazz == null) {
System.out.print("WARNING - $errorMessage\n")
} else {
System.out.print("${clazz.name}: WARNING - $errorMessage\n")
}
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment