From 8c455d9e087d91c67894d4b421e7d5b18028dc6a Mon Sep 17 00:00:00 2001 From: Dmitry Gridin Date: Mon, 27 Jan 2020 23:32:25 +0700 Subject: [PATCH] Create `AbstractDiagnosticBasedInspection` --- ...tractDiagnosticBasedMigrationInspection.kt | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 idea/src/org/jetbrains/kotlin/idea/inspections/migration/AbstractDiagnosticBasedMigrationInspection.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/migration/AbstractDiagnosticBasedMigrationInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/migration/AbstractDiagnosticBasedMigrationInspection.kt new file mode 100644 index 00000000000..9ccd209b14a --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/migration/AbstractDiagnosticBasedMigrationInspection.kt @@ -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( + private val diagnosticFactory: DiagnosticFactoryWithPsiElement, + private val elementType: Class, + private val customIntentionFactory: ((Diagnostic) -> IntentionAction?)? = null, +) : AbstractKotlinInspection() { + override fun checkFile(file: PsiFile, manager: InspectionManager, isOnTheFly: Boolean): Array? { + 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() + + 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 +} \ No newline at end of file