From 15930a42b89470431642e825fff785f95b6c60cc Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Wed, 13 Jan 2016 22:21:06 +0300 Subject: [PATCH] Fixed containingDeclaration for descriptors inside init-blocks for the case of no primary constructor KT-10226 Wrong Imports optimization ("Unresolved reference" is being added) #KT-10226 Fixed --- .../ClassResolutionScopesSupport.kt | 45 ++++++++------- .../lazy/descriptors/LazyClassDescriptor.java | 56 ++++++++++++++++--- .../editor/optimizeImports/KT10226.kt | 10 ++++ .../editor/optimizeImports/KT10226.kt.after | 10 ++++ .../imports/OptimizeImportsTestGenerated.java | 6 ++ 5 files changed, 100 insertions(+), 27 deletions(-) create mode 100644 idea/testData/editor/optimizeImports/KT10226.kt create mode 100644 idea/testData/editor/optimizeImports/KT10226.kt.after diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/ClassResolutionScopesSupport.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/ClassResolutionScopesSupport.kt index a9999cc761e..7218266d214 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/ClassResolutionScopesSupport.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/ClassResolutionScopesSupport.kt @@ -31,8 +31,7 @@ import java.util.* class ClassResolutionScopesSupport( private val classDescriptor: ClassDescriptor, storageManager: StorageManager, - private val getOuterScope: () -> LexicalScope, - private val primaryConstructorParameters: List? = null + private val getOuterScope: () -> LexicalScope ) { private fun scopeWithGenerics(parent: LexicalScope): LexicalScopeImpl { return LexicalScopeImpl(parent, classDescriptor, false, null, LexicalScopeKind.CLASS_HEADER) { @@ -76,24 +75,6 @@ class ClassResolutionScopesSupport( } } - val scopeForInitializerResolution: () -> LexicalScope = storageManager.createLazyValue { - val primaryConstructor = classDescriptor.unsubstitutedPrimaryConstructor ?: - return@createLazyValue scopeForMemberDeclarationResolution() - assert(primaryConstructorParameters != null) { - "primary constructor parameters must be not null, because primary constructor exist: $primaryConstructor" - } - LexicalScopeImpl(scopeForMemberDeclarationResolution(), primaryConstructor, false, null, - LexicalScopeKind.CLASS_INITIALIZER) { - primaryConstructorParameters!!.forEachIndexed { - index, parameter -> - if (!parameter.hasValOrVar()) { - addVariableDescriptor(primaryConstructor.valueParameters[index]) - } - } - } - } - - fun ClassDescriptor.getAllSuperclassesWithoutAny(): List { val superClasses = SmartList() var parent: ClassDescriptor? = getSuperClassNotAny() @@ -151,3 +132,27 @@ class ClassResolutionScopesSupport( private val createThrowingLexicalScope: (Boolean) -> LexicalScope = { ThrowingLexicalScope() } } } + +fun scopeForInitializerResolution( + classDescriptor: LazyClassDescriptor, + parentDescriptor: DeclarationDescriptor, + primaryConstructorParameters: List +): LexicalScope { + return LexicalScopeImpl( + classDescriptor.scopeForMemberDeclarationResolution, + parentDescriptor, + false, + null, + LexicalScopeKind.CLASS_INITIALIZER + ) { + if (primaryConstructorParameters.isNotEmpty()) { + val parameterDescriptors = classDescriptor.unsubstitutedPrimaryConstructor!!.valueParameters + assert(parameterDescriptors.size == primaryConstructorParameters.size) + for ((parameter, descriptor) in primaryConstructorParameters.zip(parameterDescriptors)) { + if (!parameter.hasValOrVar()) { + addVariableDescriptor(descriptor) + } + } + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java index 079deb318a1..926a211cda0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorBase; +import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl; import org.jetbrains.kotlin.incremental.components.NoLookupLocation; import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.name.Name; @@ -54,10 +55,7 @@ import org.jetbrains.kotlin.storage.MemoizedFunctionToNotNull; import org.jetbrains.kotlin.storage.NotNullLazyValue; import org.jetbrains.kotlin.storage.NullableLazyValue; import org.jetbrains.kotlin.storage.StorageManager; -import org.jetbrains.kotlin.types.AbstractClassTypeConstructor; -import org.jetbrains.kotlin.types.KotlinType; -import org.jetbrains.kotlin.types.TypeConstructor; -import org.jetbrains.kotlin.types.TypeUtils; +import org.jetbrains.kotlin.types.*; import java.util.ArrayList; import java.util.Collection; @@ -103,11 +101,13 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes private final ClassResolutionScopesSupport resolutionScopesSupport; private final NotNullLazyValue> parameters; + private final NotNullLazyValue scopeForInitializerResolution; + public LazyClassDescriptor( @NotNull final LazyClassContext c, @NotNull DeclarationDescriptor containingDeclaration, @NotNull Name name, - @NotNull KtClassLikeInfo classLikeInfo + @NotNull final KtClassLikeInfo classLikeInfo ) { super(c.getStorageManager(), containingDeclaration, name, KotlinSourceElementKt.toSourceElement(classLikeInfo.getCorrespondingClassOrObject()) @@ -239,7 +239,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes public LexicalScope invoke() { return getOuterScope(); } - }, classLikeInfo.getPrimaryConstructorParameters()); + }); this.parameters = c.getStorageManager().createLazyValue(new Function0>() { @Override @@ -264,6 +264,48 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes } }); + this.scopeForInitializerResolution = storageManager.createLazyValue(new Function0() { + @Override + public LexicalScope invoke() { + return ClassResolutionScopesSupportKt.scopeForInitializerResolution(LazyClassDescriptor.this, + createInitializerScopeParent(), + classLikeInfo.getPrimaryConstructorParameters()); + } + }); + } + + @NotNull + private DeclarationDescriptor createInitializerScopeParent() { + ConstructorDescriptor primaryConstructor = getUnsubstitutedPrimaryConstructor(); + if (primaryConstructor != null) return primaryConstructor; + + return new FunctionDescriptorImpl(LazyClassDescriptor.this, null, Annotations.Companion.getEMPTY(), + Name.special(""), + CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE) { + @NotNull + @Override + protected FunctionDescriptorImpl createSubstitutedCopy( + @NotNull DeclarationDescriptor newOwner, + @Nullable FunctionDescriptor original, + @NotNull Kind kind, + @Nullable Name newName, + boolean preserveSource + ) { + throw new UnsupportedOperationException(); + } + + @NotNull + @Override + public FunctionDescriptor copy( + DeclarationDescriptor newOwner, + Modality modality, + Visibility visibility, + Kind kind, + boolean copyOverrides + ) { + throw new UnsupportedOperationException(); + } + }; } // NOTE: Called from constructor! @@ -319,7 +361,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes @Override @NotNull public LexicalScope getScopeForInitializerResolution() { - return resolutionScopesSupport.getScopeForInitializerResolution().invoke(); + return scopeForInitializerResolution.invoke(); } @NotNull diff --git a/idea/testData/editor/optimizeImports/KT10226.kt b/idea/testData/editor/optimizeImports/KT10226.kt new file mode 100644 index 00000000000..03e9f38e1bb --- /dev/null +++ b/idea/testData/editor/optimizeImports/KT10226.kt @@ -0,0 +1,10 @@ +import java.io.File + +class C { + constructor(file: File) + + init { + val xxx = 1 + xxx.inc() + } +} \ No newline at end of file diff --git a/idea/testData/editor/optimizeImports/KT10226.kt.after b/idea/testData/editor/optimizeImports/KT10226.kt.after new file mode 100644 index 00000000000..03e9f38e1bb --- /dev/null +++ b/idea/testData/editor/optimizeImports/KT10226.kt.after @@ -0,0 +1,10 @@ +import java.io.File + +class C { + constructor(file: File) + + init { + val xxx = 1 + xxx.inc() + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/imports/OptimizeImportsTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/imports/OptimizeImportsTestGenerated.java index fcef2049a5e..e54b3806378 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/imports/OptimizeImportsTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/imports/OptimizeImportsTestGenerated.java @@ -137,6 +137,12 @@ public class OptimizeImportsTestGenerated extends AbstractOptimizeImportsTest { doTest(fileName); } + @TestMetadata("KT10226.kt") + public void testKT10226() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/optimizeImports/KT10226.kt"); + doTest(fileName); + } + @TestMetadata("KT9875.kt") public void testKT9875() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/optimizeImports/KT9875.kt");