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.PsiElementFinderImpl;
import com.intellij.psi.impl.file.PsiPackageImpl; import com.intellij.psi.impl.file.PsiPackageImpl;
import com.intellij.psi.impl.file.impl.JavaFileManager; 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.search.GlobalSearchScope;
import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.reference.SoftReference; import com.intellij.reference.SoftReference;
@@ -41,6 +42,7 @@ import kotlin.collections.CollectionsKt;
import kotlin.jvm.functions.Function1; import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.idea.KotlinLanguage;
import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus; import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.ClassId;
@@ -62,6 +64,7 @@ public class KotlinJavaPsiFacade {
private volatile SoftReference<PackageCache> packageCache; private volatile SoftReference<PackageCache> packageCache;
private final Project project; private final Project project;
private final LightModifierList emptyModifierList;
public static KotlinJavaPsiFacade getInstance(Project project) { public static KotlinJavaPsiFacade getInstance(Project project) {
return ServiceManager.getService(project, KotlinJavaPsiFacade.class); return ServiceManager.getService(project, KotlinJavaPsiFacade.class);
@@ -70,6 +73,8 @@ public class KotlinJavaPsiFacade {
public KotlinJavaPsiFacade(@NotNull Project project) { public KotlinJavaPsiFacade(@NotNull Project project) {
this.project = project; this.project = project;
emptyModifierList = new LightModifierList(PsiManager.getInstance(project), KotlinLanguage.INSTANCE);
final PsiModificationTracker modificationTracker = PsiManager.getInstance(project).getModificationTracker(); final PsiModificationTracker modificationTracker = PsiManager.getInstance(project).getModificationTracker();
MessageBus bus = project.getMessageBus(); 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) { 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 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.*
import com.intellij.psi.impl.compiled.ClsTypeElementImpl import com.intellij.psi.impl.compiled.ClsTypeElementImpl
import com.intellij.psi.impl.light.LightMethod import com.intellij.psi.impl.light.LightMethod
import com.intellij.psi.impl.light.LightModifierList
import com.intellij.psi.scope.PsiScopeProcessor import com.intellij.psi.scope.PsiScopeProcessor
import com.intellij.psi.util.* import com.intellij.psi.util.*
import com.intellij.util.IncorrectOperationException 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.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
interface KtLightMethod : PsiMethod, KtLightDeclaration<KtDeclaration, PsiMethod> { interface KtLightMethod : PsiMethod, KtLightDeclaration<KtDeclaration, PsiMethod> {
@@ -53,6 +55,8 @@ sealed class KtLightMethodImpl(
delegateTypeElement?.let { ClsTypeElementImpl(this, it.canonicalText, /*ClsTypeElementImpl.VARIANCE_NONE */ 0.toChar()) } delegateTypeElement?.let { ClsTypeElementImpl(this, it.canonicalText, /*ClsTypeElementImpl.VARIANCE_NONE */ 0.toChar()) }
} }
private val calculatingReturnType = ThreadLocal<Boolean>()
override fun getContainingClass(): KtLightClass = super.getContainingClass() as KtLightClass override fun getContainingClass(): KtLightClass = super.getContainingClass() as KtLightClass
private val paramsList: CachedValue<PsiParameterList> by lazy(LazyThreadSafetyMode.PUBLICATION) { private val paramsList: CachedValue<PsiParameterList> by lazy(LazyThreadSafetyMode.PUBLICATION) {
@@ -141,7 +145,12 @@ sealed class KtLightMethodImpl(
else clsDelegate.modifierList 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 override fun getNameIdentifier() = lightIdentifier
@@ -206,7 +215,15 @@ sealed class KtLightMethodImpl(
// which is relied upon by java type inference // which is relied upon by java type inference
override fun getReturnTypeElement(): PsiTypeElement? = returnTypeElem 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 { companion object Factory {
fun create( fun create(