to avoid running resolve under ClsTypeElement lock, return empty modifier list if we're currently calculating the return type (the modifier list is requested to apply type annotations, and we don't care about them anyway)

#KT-12966 Fixed
This commit is contained in:
Dmitry Jemerov
2016-10-07 19:09:55 +02:00
parent e55c82d3f3
commit ce0d81f670
2 changed files with 28 additions and 2 deletions
@@ -28,6 +28,7 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.PsiElementFinderImpl;
import com.intellij.psi.impl.file.PsiPackageImpl;
import com.intellij.psi.impl.file.impl.JavaFileManager;
import com.intellij.psi.impl.light.LightModifierList;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.reference.SoftReference;
@@ -41,6 +42,7 @@ import kotlin.collections.CollectionsKt;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.idea.KotlinLanguage;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
import org.jetbrains.kotlin.name.ClassId;
@@ -62,6 +64,7 @@ public class KotlinJavaPsiFacade {
private volatile SoftReference<PackageCache> packageCache;
private final Project project;
private final LightModifierList emptyModifierList;
public static KotlinJavaPsiFacade getInstance(Project project) {
return ServiceManager.getService(project, KotlinJavaPsiFacade.class);
@@ -70,6 +73,8 @@ public class KotlinJavaPsiFacade {
public KotlinJavaPsiFacade(@NotNull Project project) {
this.project = project;
emptyModifierList = new LightModifierList(PsiManager.getInstance(project), KotlinLanguage.INSTANCE);
final PsiModificationTracker modificationTracker = PsiManager.getInstance(project).getModificationTracker();
MessageBus bus = project.getMessageBus();
@@ -88,6 +93,10 @@ public class KotlinJavaPsiFacade {
});
}
public LightModifierList getEmptyModifierList() {
return emptyModifierList;
}
public PsiClass findClass(@NotNull ClassId classId, @NotNull GlobalSearchScope scope) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); // We hope this method is being called often enough to cancel daemon processes smoothly
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.TextRange
import com.intellij.psi.*
import com.intellij.psi.impl.compiled.ClsTypeElementImpl
import com.intellij.psi.impl.light.LightMethod
import com.intellij.psi.impl.light.LightModifierList
import com.intellij.psi.scope.PsiScopeProcessor
import com.intellij.psi.util.*
import com.intellij.util.IncorrectOperationException
@@ -33,6 +34,7 @@ import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
interface KtLightMethod : PsiMethod, KtLightDeclaration<KtDeclaration, PsiMethod> {
@@ -53,6 +55,8 @@ sealed class KtLightMethodImpl(
delegateTypeElement?.let { ClsTypeElementImpl(this, it.canonicalText, /*ClsTypeElementImpl.VARIANCE_NONE */ 0.toChar()) }
}
private val calculatingReturnType = ThreadLocal<Boolean>()
override fun getContainingClass(): KtLightClass = super.getContainingClass() as KtLightClass
private val paramsList: CachedValue<PsiParameterList> by lazy(LazyThreadSafetyMode.PUBLICATION) {
@@ -141,7 +145,12 @@ sealed class KtLightMethodImpl(
else clsDelegate.modifierList
}
override fun getModifierList() = _modifierList
override fun getModifierList(): PsiModifierList {
if (calculatingReturnType.get() == true) {
return KotlinJavaPsiFacade.getInstance(project).emptyModifierList
}
return _modifierList
}
override fun getNameIdentifier() = lightIdentifier
@@ -206,7 +215,15 @@ sealed class KtLightMethodImpl(
// which is relied upon by java type inference
override fun getReturnTypeElement(): PsiTypeElement? = returnTypeElem
override fun getReturnType() = returnTypeElement?.type
override fun getReturnType(): PsiType? {
calculatingReturnType.set(true)
try {
return returnTypeElement?.type
}
finally {
calculatingReturnType.set(false)
}
}
companion object Factory {
fun create(