Skip to content

Instantly share code, notes, and snippets.

@dkandalov
Last active May 9, 2021 16:41
Show Gist options
  • Save dkandalov/3f9f6ee81f2b8e08f677dff72c77ebb8 to your computer and use it in GitHub Desktop.
Save dkandalov/3f9f6ee81f2b8e08f677dff72c77ebb8 to your computer and use it in GitHub Desktop.
Kotlin space police inspection (see https://github.com/dkandalov/live-plugin)
import com.intellij.codeInspection.LocalQuickFix
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.ProblemHighlightType.WEAK_WARNING
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.lang.ASTFactory
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiWhiteSpace
import liveplugin.registerInspection
import liveplugin.show
import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
import org.jetbrains.kotlin.idea.util.getLineCount
import org.jetbrains.kotlin.psi.*
// depends-on-plugin org.jetbrains.kotlin
registerInspection(RedundantEmptyLinesInspection())
if (!isIdeStartup) {
show("Loaded RedundantEmptyLinesInspection")
}
class RedundantEmptyLinesInspection : AbstractKotlinInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : KtVisitorVoid() {
override fun visitWhiteSpace(space: PsiWhiteSpace) {
val parent = space.parent
val nextSibling = space.nextSibling
val prevSibling = space.prevSibling
val lineCount = space.getLineCount()
if (lineCount >= 3 && parent is KtClassBody
&& (prevSibling == parent.lBrace || nextSibling == parent.rBrace)
) return space.addTo(holder)
if (lineCount >= 3 && parent is KtBlockExpression && parent.parent !is KtScript
&& (prevSibling == parent.lBrace || nextSibling == parent.rBrace)
) return space.addTo(holder)
if (lineCount >= 3 && parent is KtFunctionLiteral
&& (prevSibling == parent.lBrace || prevSibling == parent.arrow || nextSibling == parent.rBrace)
) return space.addTo(holder)
if (lineCount >= 4) return space.addTo(holder, linesToKeep = 3)
}
}
}
override fun getDisplayName() = "Redundant empty lines"
override fun getShortName() = "Redundant empty lines"
override fun getGroupDisplayName() = "Live Plugin"
override fun isEnabledByDefault() = true
private fun PsiWhiteSpace?.addTo(holder: ProblemsHolder, linesToKeep: Int = 2) {
holder.registerProblem(
this ?: return,
"Redundant empty lines",
WEAK_WARNING,
RemoveRedundantEmptyLinesQuickFix(linesToKeep)
)
}
class RemoveRedundantEmptyLinesQuickFix(private val linesToKeep: Int) : LocalQuickFix {
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val node = (descriptor.psiElement as? PsiWhiteSpace)?.node ?: return
val trimmedWhiteSpace = node.text.lineSequence().take(linesToKeep).joinToString("\n")
node.treeParent?.replaceChild(node, ASTFactory.whitespace(trimmedWhiteSpace))
}
override fun getName() = "Remove redundant empty lines"
override fun getFamilyName() = name
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment