KotlinSpringComponentScanInspection made to support platform JamReferenceContributor
This commit is contained in:
committed by
Nikolay Krasko
parent
0cad41bb0c
commit
79abc8743e
+38
-15
@@ -1,34 +1,57 @@
|
||||
package org.jetbrains.kotlin.idea.spring.inspections
|
||||
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleUtilCore
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.jam.NonPhysicalReferenceWrapper
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import com.intellij.spring.model.highlighting.jam.SpringComponentScanInspection
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.PsiPackageReference
|
||||
import com.intellij.spring.model.jam.stereotype.SpringComponentScan
|
||||
import com.intellij.spring.model.jam.utils.SpringJamUtils
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightAnnotationForSourceEntry
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
|
||||
import org.jetbrains.kotlin.idea.inspections.registerWithElementsUnwrapped
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtStringTemplateEntry
|
||||
import org.jetbrains.kotlin.psi.KtTreeVisitorVoid
|
||||
import org.jetbrains.kotlin.psi.KtVisitorVoid
|
||||
|
||||
class KotlinSpringComponentScanInspection : AbstractKotlinInspection() {
|
||||
private val javaInspection by lazy {
|
||||
object : SpringComponentScanInspection() {
|
||||
// make base method visible
|
||||
override public fun checkClass(aClass: PsiClass, holder: ProblemsHolder, module: Module) = super.checkClass(aClass, holder, module)
|
||||
}
|
||||
}
|
||||
|
||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
|
||||
return object: KtVisitorVoid() {
|
||||
override fun visitClassOrObject(classOrObject: KtClassOrObject) {
|
||||
val module = ModuleUtilCore.findModuleForPsiElement(classOrObject) ?: return
|
||||
val lightClass = classOrObject.toLightClass() ?: return
|
||||
val tmpHolder = ProblemsHolder(holder.manager, classOrObject.containingFile, isOnTheFly)
|
||||
javaInspection.checkClass(lightClass, tmpHolder, module)
|
||||
tmpHolder.resultsArray.registerWithElementsUnwrapped(holder, isOnTheFly)
|
||||
val beansPackagesScan = SpringJamUtils.getInstance().getBeansPackagesScan(lightClass)
|
||||
.filterIsInstance<SpringComponentScan>()
|
||||
val kotlinAnnotations = beansPackagesScan
|
||||
.mapNotNull { (it.annotation as? KtLightAnnotationForSourceEntry)?.kotlinOrigin }
|
||||
if (kotlinAnnotations.isEmpty()) return
|
||||
val literalVisitor = PsiPackageReferenceChecker(holder)
|
||||
for (kotlinAnnotation in kotlinAnnotations) {
|
||||
kotlinAnnotation.accept(literalVisitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class PsiPackageReferenceChecker(private val holder: ProblemsHolder) : KtTreeVisitorVoid() {
|
||||
override fun visitStringTemplateEntry(entry: KtStringTemplateEntry) {
|
||||
for (reference in entry.references) {
|
||||
val packageReference = psiPackageReference(reference) ?: continue
|
||||
if (packageReference.multiResolve(false).isEmpty()) {
|
||||
holder.registerProblem(reference, //registering on physical reference
|
||||
ProblemsHolder.unresolvedReferenceMessage(packageReference), //but getting message from logical reference
|
||||
ProblemHighlightType.LIKE_UNKNOWN_SYMBOL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun psiPackageReference(reference: PsiReference): PsiPackageReference? = when (reference) {
|
||||
is PsiPackageReference -> reference
|
||||
is NonPhysicalReferenceWrapper -> psiPackageReference(reference.wrappedReference)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user