Do not run unused symbol inspection if declaration in used in more than 3 scripts
This commit is contained in:
@@ -19,18 +19,27 @@ package org.jetbrains.kotlin.idea.search
|
|||||||
import com.intellij.openapi.fileTypes.FileType
|
import com.intellij.openapi.fileTypes.FileType
|
||||||
import com.intellij.openapi.fileTypes.FileTypeRegistry
|
import com.intellij.openapi.fileTypes.FileTypeRegistry
|
||||||
import com.intellij.openapi.progress.ProgressIndicator
|
import com.intellij.openapi.progress.ProgressIndicator
|
||||||
|
import com.intellij.openapi.progress.ProgressManager
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.roots.FileIndexFacade
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.psi.impl.cache.impl.id.IdIndex
|
||||||
|
import com.intellij.psi.impl.cache.impl.id.IdIndexEntry
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.search.LocalSearchScope
|
import com.intellij.psi.search.LocalSearchScope
|
||||||
import com.intellij.psi.search.PsiSearchHelper
|
import com.intellij.psi.search.PsiSearchHelper
|
||||||
import com.intellij.psi.search.SearchScope
|
import com.intellij.psi.search.SearchScope
|
||||||
import com.intellij.psi.search.searches.ReferencesSearch
|
import com.intellij.psi.search.searches.ReferencesSearch
|
||||||
|
import com.intellij.util.Processor
|
||||||
|
import com.intellij.util.indexing.FileBasedIndex
|
||||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||||
import org.jetbrains.kotlin.idea.util.compat.psiSearchHelperInstance
|
import org.jetbrains.kotlin.idea.util.compat.psiSearchHelperInstance
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.script.findScriptDefinition
|
||||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||||
|
|
||||||
infix fun SearchScope.and(otherScope: SearchScope): SearchScope = intersectWith(otherScope)
|
infix fun SearchScope.and(otherScope: SearchScope): SearchScope = intersectWith(otherScope)
|
||||||
@@ -108,7 +117,36 @@ fun PsiSearchHelper.isCheapEnoughToSearchConsideringOperators(
|
|||||||
fileToIgnoreOccurrencesIn: PsiFile?,
|
fileToIgnoreOccurrencesIn: PsiFile?,
|
||||||
progress: ProgressIndicator?
|
progress: ProgressIndicator?
|
||||||
): PsiSearchHelper.SearchCostResult {
|
): PsiSearchHelper.SearchCostResult {
|
||||||
if (OperatorConventions.isConventionName(Name.identifier(name))) return PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES
|
if (OperatorConventions.isConventionName(Name.identifier(name))) {
|
||||||
|
return PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isCheapToSearchUsagesInScripts(scope.restrictToKotlinSources(), name)) {
|
||||||
|
return PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES
|
||||||
|
}
|
||||||
|
|
||||||
return isCheapEnoughToSearch(name, scope, fileToIgnoreOccurrencesIn, progress)
|
return isCheapEnoughToSearch(name, scope, fileToIgnoreOccurrencesIn, progress)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isCheapToSearchUsagesInScripts(scope: GlobalSearchScope, name: String): Boolean {
|
||||||
|
val project = scope.project ?: return true
|
||||||
|
|
||||||
|
var scriptsCount = 0
|
||||||
|
val processor = object : Processor<VirtualFile> {
|
||||||
|
override fun process(file: VirtualFile): Boolean {
|
||||||
|
ProgressManager.checkCanceled()
|
||||||
|
if (findScriptDefinition(file, project) == null) return true
|
||||||
|
return scriptsCount++ < 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val index = FileIndexFacade.getInstance(project)
|
||||||
|
return runReadAction {
|
||||||
|
FileBasedIndex.getInstance().processFilesContainingAllKeys(
|
||||||
|
IdIndex.NAME,
|
||||||
|
listOf(IdIndexEntry(name, true)),
|
||||||
|
scope,
|
||||||
|
null,
|
||||||
|
{ file -> !index.shouldBeFound(scope, file) || processor.process(file) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import com.intellij.psi.PsiElement
|
|||||||
import com.intellij.psi.PsiElementVisitor
|
import com.intellij.psi.PsiElementVisitor
|
||||||
import com.intellij.psi.PsiReference
|
import com.intellij.psi.PsiReference
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
|
import com.intellij.psi.search.PsiSearchHelper.SearchCostResult
|
||||||
import com.intellij.psi.search.PsiSearchHelper.SearchCostResult.*
|
import com.intellij.psi.search.PsiSearchHelper.SearchCostResult.*
|
||||||
import com.intellij.psi.search.SearchScope
|
import com.intellij.psi.search.SearchScope
|
||||||
import com.intellij.psi.search.searches.DefinitionsScopedSearch
|
import com.intellij.psi.search.searches.DefinitionsScopedSearch
|
||||||
@@ -109,7 +110,34 @@ class UnusedSymbolInspection : AbstractKotlinInspection() {
|
|||||||
}
|
}
|
||||||
else -> return false
|
else -> return false
|
||||||
}
|
}
|
||||||
return lightElement != null && javaInspection.isEntryPoint(lightElement)
|
|
||||||
|
if (lightElement == null) return false
|
||||||
|
|
||||||
|
if (isCheapEnoughToSearchUsages(declaration) == TOO_MANY_OCCURRENCES) return false
|
||||||
|
|
||||||
|
return javaInspection.isEntryPoint(lightElement)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isCheapEnoughToSearchUsages(declaration: KtNamedDeclaration): SearchCostResult {
|
||||||
|
val project = declaration.project
|
||||||
|
val psiSearchHelper = psiSearchHelperInstance(project)
|
||||||
|
|
||||||
|
val useScope = psiSearchHelper.getUseScope(declaration)
|
||||||
|
if (useScope is GlobalSearchScope) {
|
||||||
|
var zeroOccurrences = true
|
||||||
|
for (name in listOf(declaration.name) + declaration.getAccessorNames() + listOfNotNull(declaration.getClassNameForCompanionObject())) {
|
||||||
|
if (name == null) continue
|
||||||
|
when (psiSearchHelper.isCheapEnoughToSearchConsideringOperators(name, useScope, null, null)) {
|
||||||
|
ZERO_OCCURRENCES -> {
|
||||||
|
} // go on, check other names
|
||||||
|
FEW_OCCURRENCES -> zeroOccurrences = false
|
||||||
|
TOO_MANY_OCCURRENCES -> return TOO_MANY_OCCURRENCES // searching usages is too expensive; behave like it is used
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zeroOccurrences) return ZERO_OCCURRENCES
|
||||||
|
}
|
||||||
|
return FEW_OCCURRENCES
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtProperty.isSerializationImplicitlyUsedField(): Boolean {
|
private fun KtProperty.isSerializationImplicitlyUsedField(): Boolean {
|
||||||
@@ -223,18 +251,13 @@ class UnusedSymbolInspection : AbstractKotlinInspection() {
|
|||||||
val project = declaration.project
|
val project = declaration.project
|
||||||
val psiSearchHelper = psiSearchHelperInstance(project)
|
val psiSearchHelper = psiSearchHelperInstance(project)
|
||||||
|
|
||||||
val useScope = declaration.useScope
|
val useScope = psiSearchHelper.getUseScope(declaration)
|
||||||
val restrictedScope = if (useScope is GlobalSearchScope) {
|
val restrictedScope = if (useScope is GlobalSearchScope) {
|
||||||
var zeroOccurrences = true
|
val enoughToSearchUsages = isCheapEnoughToSearchUsages(declaration)
|
||||||
|
val zeroOccurrences = when (enoughToSearchUsages) {
|
||||||
for (name in listOf(declaration.name) + declaration.getAccessorNames() + listOfNotNull(declaration.getClassNameForCompanionObject())) {
|
ZERO_OCCURRENCES -> true
|
||||||
if (name == null) continue
|
FEW_OCCURRENCES -> false
|
||||||
when (psiSearchHelper.isCheapEnoughToSearchConsideringOperators(name, useScope, null, null)) {
|
TOO_MANY_OCCURRENCES -> return true // searching usages is too expensive; behave like it is used
|
||||||
ZERO_OCCURRENCES -> {
|
|
||||||
} // go on, check other names
|
|
||||||
FEW_OCCURRENCES -> zeroOccurrences = false
|
|
||||||
TOO_MANY_OCCURRENCES -> return true // searching usages is too expensive; behave like it is used
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zeroOccurrences && !declaration.hasActualModifier()) {
|
if (zeroOccurrences && !declaration.hasActualModifier()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user