Fix "Illegal Android Identifier" inspection reports non-instrumentation unit tests (KT-22168)
This commit is contained in:
+61
-4
@@ -16,20 +16,36 @@
|
||||
|
||||
package org.jetbrains.kotlin.android.inspection
|
||||
|
||||
import com.android.builder.model.AndroidProject.ARTIFACT_UNIT_TEST
|
||||
import com.android.tools.idea.AndroidPsiUtils
|
||||
import com.android.tools.idea.gradle.project.model.AndroidModuleModel
|
||||
import com.intellij.codeInspection.LocalInspectionToolSession
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.roots.ProjectRootModificationTracker
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import org.jetbrains.android.facet.AndroidFacet
|
||||
import org.jetbrains.kotlin.android.getAndroidFacetForFile
|
||||
import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
|
||||
import org.jetbrains.kotlin.idea.quickfix.RenameIdentifierFix
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
import org.jetbrains.kotlin.psi.KtVisitorVoid
|
||||
import java.io.File
|
||||
|
||||
class IllegalIdentifierInspection : AbstractKotlinInspection() {
|
||||
private class JunitPaths(val paths: List<File>, val generationId: Long) {
|
||||
companion object : Key<JunitPaths>("AndroidModuleJunitPaths")
|
||||
}
|
||||
|
||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
|
||||
return object : KtVisitorVoid() {
|
||||
override fun visitElement(element: PsiElement) {
|
||||
@@ -44,13 +60,37 @@ class IllegalIdentifierInspection : AbstractKotlinInspection() {
|
||||
if (unquotedName.isEmpty()) return
|
||||
|
||||
if (!unquotedName.all { isValidDalvikCharacter(it) } && checkAndroidFacet(element)) {
|
||||
holder.registerProblem(element,
|
||||
"Identifier not allowed in Android projects",
|
||||
ProblemHighlightType.GENERIC_ERROR,
|
||||
RenameIdentifierFix())
|
||||
if (element.isInUnitTests()) {
|
||||
return
|
||||
}
|
||||
|
||||
holder.registerProblem(
|
||||
element,
|
||||
"Identifier not allowed in Android projects",
|
||||
ProblemHighlightType.GENERIC_ERROR,
|
||||
RenameIdentifierFix()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun PsiElement.isInUnitTests(): Boolean {
|
||||
val containingFile = containingFile?.virtualFile?.let { getIoFile(it) }
|
||||
val module = AndroidPsiUtils.getModuleSafely(this)
|
||||
|
||||
if (module != null && containingFile != null) {
|
||||
val currentGenerationId = ProjectRootModificationTracker.getInstance(module.project).modificationCount
|
||||
val junitTestPaths = module.getUserData(JunitPaths)
|
||||
?.takeIf { it.generationId == currentGenerationId }
|
||||
?: JunitPaths(getJunitTestPaths(module), currentGenerationId).also { module.putUserData(JunitPaths, it) }
|
||||
|
||||
if (junitTestPaths.paths.any { containingFile.startsWith(it) }) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun checkAndroidFacet(element: PsiElement): Boolean {
|
||||
return element.getAndroidFacetForFile() != null || ApplicationManager.getApplication().isUnitTestMode
|
||||
}
|
||||
@@ -70,4 +110,21 @@ class IllegalIdentifierInspection : AbstractKotlinInspection() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getJunitTestPaths(module: Module): List<File> {
|
||||
val androidFacet = AndroidFacet.getInstance(module) ?: return emptyList()
|
||||
val androidModuleModel = AndroidModuleModel.get(androidFacet) ?: return emptyList()
|
||||
|
||||
return androidModuleModel.getTestSourceProviders(ARTIFACT_UNIT_TEST).flatMap { it.javaDirectories }
|
||||
}
|
||||
|
||||
private fun getIoFile(virtualFile: VirtualFile): File? {
|
||||
var path = virtualFile.path
|
||||
|
||||
// Taken from LocalFileSystemBase.convertToIOFile
|
||||
if (StringUtil.endsWithChar(path, ':') && path.length == 2 && SystemInfo.isWindows) {
|
||||
path += "/"
|
||||
}
|
||||
|
||||
return File(path).takeIf { it.exists() }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user