diff options
Diffstat (limited to 'plugins/kotlin/fe10-analyze/safe-analyze-utils/src/org/jetbrains/kotlin/idea/util/safeAnalyze.kt')
-rw-r--r-- | plugins/kotlin/fe10-analyze/safe-analyze-utils/src/org/jetbrains/kotlin/idea/util/safeAnalyze.kt | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/plugins/kotlin/fe10-analyze/safe-analyze-utils/src/org/jetbrains/kotlin/idea/util/safeAnalyze.kt b/plugins/kotlin/fe10-analyze/safe-analyze-utils/src/org/jetbrains/kotlin/idea/util/safeAnalyze.kt new file mode 100644 index 000000000000..3e89c6a4c15d --- /dev/null +++ b/plugins/kotlin/fe10-analyze/safe-analyze-utils/src/org/jetbrains/kotlin/idea/util/safeAnalyze.kt @@ -0,0 +1,54 @@ +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.util + +import com.intellij.injected.editor.VirtualFileWindow +import com.intellij.openapi.roots.ProjectRootManager +import com.intellij.openapi.vfs.NonPhysicalFileSystem +import com.intellij.psi.PsiElement +import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes +import org.jetbrains.jps.model.java.JavaSourceRootProperties +import org.jetbrains.jps.model.module.JpsModuleSourceRootType +import org.jetbrains.kotlin.config.ALL_KOTLIN_SOURCE_ROOT_TYPES +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + +/** + * Best effort to analyze element: + * - Best effort for file that is out of source root scope: NoDescriptorForDeclarationException could be swallowed + * - Do not swallow NoDescriptorForDeclarationException during analysis for in source scope files + */ +inline fun <T> PsiElement.actionUnderSafeAnalyzeBlock( + crossinline action: () -> T, + crossinline fallback: () -> T +): T = try { + action() +} catch (e: Exception) { + e.returnIfNoDescriptorForDeclarationException(condition = { + val file = containingFile + it && (!file.isPhysical || !file.isUnderKotlinSourceRootTypes()) + }) { fallback() } +} + +val Exception.isItNoDescriptorForDeclarationException: Boolean + get() = this is NoDescriptorForDeclarationException || cause?.safeAs<Exception>()?.isItNoDescriptorForDeclarationException == true + +inline fun <T> Exception.returnIfNoDescriptorForDeclarationException( + crossinline condition: (Boolean) -> Boolean = { v -> v }, + crossinline computable: () -> T +): T = + if (condition(this.isItNoDescriptorForDeclarationException)) { + computable() + } else { + throw this + } + +val KOTLIN_AWARE_SOURCE_ROOT_TYPES: Set<JpsModuleSourceRootType<JavaSourceRootProperties>> = + JavaModuleSourceRootTypes.SOURCES + ALL_KOTLIN_SOURCE_ROOT_TYPES + +fun PsiElement?.isUnderKotlinSourceRootTypes(): Boolean { + val ktFile = this?.containingFile.safeAs<KtFile>() ?: return false + val file = ktFile.virtualFile?.takeIf { it !is VirtualFileWindow && it.fileSystem !is NonPhysicalFileSystem } ?: return false + val projectFileIndex = ProjectRootManager.getInstance(ktFile.project).fileIndex + return projectFileIndex.isUnderSourceRootOfType(file, KOTLIN_AWARE_SOURCE_ROOT_TYPES) +} |