Create AbstractDiagnosticBasedInspection

This commit is contained in:
Dmitry Gridin
2020-01-27 23:32:25 +07:00
parent ae39d748e4
commit 8c455d9e08
@@ -0,0 +1,75 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.inspections.migration
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.codeInspection.InspectionManager
import com.intellij.codeInspection.IntentionWrapper
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactoryWithPsiElement
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks
import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
import org.jetbrains.kotlin.idea.quickfix.QuickFixes
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtTreeVisitorVoid
abstract class AbstractDiagnosticBasedMigrationInspection<T : KtElement>(
private val diagnosticFactory: DiagnosticFactoryWithPsiElement<T, *>,
private val elementType: Class<T>,
private val customIntentionFactory: ((Diagnostic) -> IntentionAction?)? = null,
) : AbstractKotlinInspection() {
override fun checkFile(file: PsiFile, manager: InspectionManager, isOnTheFly: Boolean): Array<ProblemDescriptor>? {
if (file !is KtFile) return null
val diagnostics by lazy {
file.analyzeWithAllCompilerChecks().bindingContext.diagnostics
}
val actionsFactory = QuickFixes.getInstance().getActionFactories(diagnosticFactory).singleOrNull() ?: error("Must have one factory")
val problemDescriptors = arrayListOf<ProblemDescriptor>()
file.accept(
object : KtTreeVisitorVoid() {
override fun visitKtElement(element: KtElement) {
super.visitKtElement(element)
if (!elementType.isInstance(element) || element.textLength == 0) return
val diagnostic = diagnostics.forElement(element)
.filter { it.factory == diagnosticFactory }
.ifEmpty { return }
.singleOrNull()
?: error("Must have one diagnostic")
val intentionAction = (if (customIntentionFactory != null)
customIntentionFactory.invoke(diagnostic)
else
actionsFactory.createActions(diagnostic).singleOrNull())
?: error("Must have one fix")
val text = descriptionMessage() ?: DefaultErrorMessages.render(diagnostic)
problemDescriptors.add(
manager.createProblemDescriptor(
element,
text,
false,
arrayOf(IntentionWrapper(intentionAction, file)),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
),
)
}
},
)
return problemDescriptors.toTypedArray()
}
protected open fun descriptionMessage(): String? = null
}