From 989f07962b0cc3e004c277364beb24d56250e9b5 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Wed, 25 Feb 2015 13:19:39 +0300 Subject: [PATCH] Write to trace in case class qualifier is a short reference to default object This allows to fix some cases when there is a difference between explicit and short reference to default object Fix shorten reference, optimize imports and import insert helper for default objects ShortenReferences always transforms default object references to shorter form for now Fix DescriptorUtils#getFqName() for default objects (affects test data mostly) Fix DescriptorUtils#getImportableDescriptor() --- .../kotlin/resolve/BindingContext.java | 3 + .../calls/tasks/TracingStrategyImpl.java | 6 +- .../util/FakeCallableDescriptorForObject.kt | 2 +- .../resolve/scopes/receivers/Qualifier.kt | 10 +- .../classObjects/importClassInClassObject.txt | 2 +- .../nestedClassInPrivateClassObject.txt | 2 +- .../tests/enum/inner/insideClassObject.txt | 12 +- .../enum/inner/redeclarationInClassObject.txt | 12 +- .../twoEnumsInClassObjectAndInnerClass.txt | 12 +- .../diagnostics/tests/imports/Imports.txt | 6 +- .../inner/selfAnnotationForClassObject.txt | 2 +- .../duplicateClass/duplicateNestedClasses.kt | 2 +- .../duplicateClass/duplicateNestedClasses.txt | 14 +-- .../diagnostics/tests/regressions/kt394.txt | 2 +- .../diagnostics/tests/scopes/kt587.txt | 2 +- .../classes/AnnotationInClassObject.txt | 2 +- .../fromLoadJava/classObjectAnnotation.txt | 2 +- .../kotlin/resolve/DescriptorUtils.java | 10 +- .../kotlin/resolve/DescriptorUtils.kt | 2 +- .../kotlin/idea/util/ImportsUtils.kt | 13 ++- .../kotlin/idea/util/ShortenReferences.kt | 108 +++++++++++++----- .../idea/imports/KotlinImportOptimizer.kt | 14 ++- .../idea/util/ImportInsertHelperImpl.kt | 8 +- .../copyPaste/imports/ClassObject.expected.kt | 4 + .../testData/copyPaste/imports/ClassObject.kt | 4 + .../imports/ClassObjectInner.expected.kt | 2 +- .../copyPaste/imports/ClassObjectInner.kt | 10 +- .../nestedClassShouldBeQualified3.txt | 2 +- .../nestedClassShouldBeQualified4.txt | 2 +- .../nestedClassShouldBeQualified5.txt | 2 +- .../DefaultObjectReference.dependency.kt | 13 +++ .../optimizeImports/DefaultObjectReference.kt | 11 ++ .../DefaultObjectReference.kt.after | 9 ++ .../privateMemberInClassObject.kt.conflicts | 2 +- .../singletonsAndStatics/after/source/Foo.kt | 4 +- .../singletonsAndStatics/after/target/Foo.kt | 8 ++ .../singletonsAndStatics/before/source/Foo.kt | 11 +- idea/testData/shortenRefs/classObject.kt | 22 +++- .../testData/shortenRefs/classObject.kt.after | 22 +++- .../imports/OptimizeImportsTestGenerated.java | 6 + 40 files changed, 278 insertions(+), 104 deletions(-) create mode 100644 idea/testData/editor/optimizeImports/DefaultObjectReference.dependency.kt create mode 100644 idea/testData/editor/optimizeImports/DefaultObjectReference.kt create mode 100644 idea/testData/editor/optimizeImports/DefaultObjectReference.kt.after diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java index e9c3c0fbacd..f91d60fb6de 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java @@ -96,6 +96,9 @@ public interface BindingContext { WritableSlice REFERENCE_TARGET = new BasicWritableSlice(DO_NOTHING); + // if 'A' really means 'A.Default' then this slice stores class descriptor for A, REFERENCE_TARGET stores descriptor Default in this case + WritableSlice SHORT_REFERENCE_TO_DEFAULT_OBJECT = + new BasicWritableSlice(DO_NOTHING); @KotlinSignature("val RESOLVED_CALL: WritableSlice>") WritableSlice> RESOLVED_CALL = new BasicWritableSlice>(DO_NOTHING); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/TracingStrategyImpl.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/TracingStrategyImpl.java index 7a1cfce657b..7dc05129cc9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/TracingStrategyImpl.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/TracingStrategyImpl.java @@ -58,7 +58,11 @@ public class TracingStrategyImpl extends AbstractTracingStrategy { descriptor = ((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall().getCandidateDescriptor(); } if (descriptor instanceof FakeCallableDescriptorForObject) { - descriptor = ((FakeCallableDescriptorForObject) descriptor).getReferencedDescriptor(); + FakeCallableDescriptorForObject fakeCallableDescriptorForObject = (FakeCallableDescriptorForObject) descriptor; + descriptor = fakeCallableDescriptorForObject.getReferencedDescriptor(); + if (fakeCallableDescriptorForObject.getClassDescriptor().getDefaultObjectDescriptor() != null) { + trace.record(SHORT_REFERENCE_TO_DEFAULT_OBJECT, reference, fakeCallableDescriptorForObject.getClassDescriptor()); + } } DeclarationDescriptor storedReference = trace.get(REFERENCE_TARGET, reference); if (storedReference == null || !ErrorUtils.isError(descriptor)) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/FakeCallableDescriptorForObject.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/FakeCallableDescriptorForObject.kt index 4bb4de410ea..49152690123 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/FakeCallableDescriptorForObject.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/FakeCallableDescriptorForObject.kt @@ -30,7 +30,7 @@ import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.resolve.descriptorUtil.getClassObjectReferenceTarget public class FakeCallableDescriptorForObject( - private val classDescriptor: ClassDescriptor + public val classDescriptor: ClassDescriptor ) : DeclarationDescriptorWithVisibility by classDescriptor.getClassObjectReferenceTarget(), VariableDescriptor { { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/receivers/Qualifier.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/receivers/Qualifier.kt index 8b41c42e97a..7527f7caed8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/receivers/Qualifier.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/receivers/Qualifier.kt @@ -148,11 +148,14 @@ private fun QualifierReceiver.resolveAsReceiverInQualifiedExpression(context: Ex } private fun QualifierReceiver.resolveAndRecordReferenceTarget(context: ExpressionTypingContext, selector: DeclarationDescriptor?) { - resultingDescriptor = resolveReferenceTarget(selector) + resultingDescriptor = resolveReferenceTarget(context, selector) context.trace.record(REFERENCE_TARGET, referenceExpression, resultingDescriptor) } -private fun QualifierReceiver.resolveReferenceTarget(selector: DeclarationDescriptor?): DeclarationDescriptor { +private fun QualifierReceiver.resolveReferenceTarget( + context: ExpressionTypingContext, + selector: DeclarationDescriptor? +): DeclarationDescriptor { if (classifier is TypeParameterDescriptor) { return classifier } @@ -168,6 +171,9 @@ private fun QualifierReceiver.resolveReferenceTarget(selector: DeclarationDescri } if (classifier is ClassDescriptor && classifier.classObjectDescriptor == selectorContainer) { + if (classifier.getDefaultObjectDescriptor() != null) { + context.trace.record(SHORT_REFERENCE_TO_DEFAULT_OBJECT, referenceExpression, classifier) + } return classifier.getClassObjectReferenceTarget() } diff --git a/compiler/testData/diagnostics/tests/classObjects/importClassInClassObject.txt b/compiler/testData/diagnostics/tests/classObjects/importClassInClassObject.txt index 05e7722f8f9..3d3ea7b4414 100644 --- a/compiler/testData/diagnostics/tests/classObjects/importClassInClassObject.txt +++ b/compiler/testData/diagnostics/tests/classObjects/importClassInClassObject.txt @@ -1,7 +1,7 @@ package package f { - internal fun test(): f.A.B + internal fun test(): f.A.Default.B internal final class A { public constructor A() diff --git a/compiler/testData/diagnostics/tests/classObjects/nestedClassInPrivateClassObject.txt b/compiler/testData/diagnostics/tests/classObjects/nestedClassInPrivateClassObject.txt index bdb0baff154..e23758f3e95 100644 --- a/compiler/testData/diagnostics/tests/classObjects/nestedClassInPrivateClassObject.txt +++ b/compiler/testData/diagnostics/tests/classObjects/nestedClassInPrivateClassObject.txt @@ -1,6 +1,6 @@ package -internal fun f1(): A.B.C.Default +internal fun f1(): A.Default.B.C.Default internal fun f2(): kotlin.Unit internal final class A { diff --git a/compiler/testData/diagnostics/tests/enum/inner/insideClassObject.txt b/compiler/testData/diagnostics/tests/enum/inner/insideClassObject.txt index fa99875489d..583ba64eb9b 100644 --- a/compiler/testData/diagnostics/tests/enum/inner/insideClassObject.txt +++ b/compiler/testData/diagnostics/tests/enum/inner/insideClassObject.txt @@ -12,10 +12,10 @@ internal final class A { public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String - internal final enum class E : kotlin.Enum { - public enum entry ENTRY : A.E { + internal final enum class E : kotlin.Enum { + public enum entry ENTRY : A.Default.E { private constructor ENTRY() - public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: A.E): kotlin.Int + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: A.Default.E): kotlin.Int public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public final override /*1*/ /*fake_override*/ fun name(): kotlin.String @@ -24,7 +24,7 @@ internal final class A { } private constructor E() - public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: A.E): kotlin.Int + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: A.Default.E): kotlin.Int public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public final override /*1*/ /*fake_override*/ fun name(): kotlin.String @@ -32,8 +32,8 @@ internal final class A { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String // Static members - public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): A.E - public final /*synthesized*/ fun values(): kotlin.Array + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): A.Default.E + public final /*synthesized*/ fun values(): kotlin.Array } } } diff --git a/compiler/testData/diagnostics/tests/enum/inner/redeclarationInClassObject.txt b/compiler/testData/diagnostics/tests/enum/inner/redeclarationInClassObject.txt index eedefe3f321..03d656f6d1e 100644 --- a/compiler/testData/diagnostics/tests/enum/inner/redeclarationInClassObject.txt +++ b/compiler/testData/diagnostics/tests/enum/inner/redeclarationInClassObject.txt @@ -12,10 +12,10 @@ internal final class A { public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String - internal final enum class E : kotlin.Enum { - public enum entry ENTRY2 : A.E { + internal final enum class E : kotlin.Enum { + public enum entry ENTRY2 : A.Default.E { private constructor ENTRY2() - public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: A.E): kotlin.Int + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: A.Default.E): kotlin.Int public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public final override /*1*/ /*fake_override*/ fun name(): kotlin.String @@ -24,7 +24,7 @@ internal final class A { } private constructor E() - public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: A.E): kotlin.Int + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: A.Default.E): kotlin.Int public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public final override /*1*/ /*fake_override*/ fun name(): kotlin.String @@ -32,8 +32,8 @@ internal final class A { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String // Static members - public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): A.E - public final /*synthesized*/ fun values(): kotlin.Array + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): A.Default.E + public final /*synthesized*/ fun values(): kotlin.Array } } diff --git a/compiler/testData/diagnostics/tests/enum/inner/twoEnumsInClassObjectAndInnerClass.txt b/compiler/testData/diagnostics/tests/enum/inner/twoEnumsInClassObjectAndInnerClass.txt index eb0f22915a1..bcd72307232 100644 --- a/compiler/testData/diagnostics/tests/enum/inner/twoEnumsInClassObjectAndInnerClass.txt +++ b/compiler/testData/diagnostics/tests/enum/inner/twoEnumsInClassObjectAndInnerClass.txt @@ -43,10 +43,10 @@ internal final class A { public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String - internal final enum class E : kotlin.Enum { - public enum entry ENTRY : A.E { + internal final enum class E : kotlin.Enum { + public enum entry ENTRY : A.Default.E { private constructor ENTRY() - public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: A.E): kotlin.Int + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: A.Default.E): kotlin.Int public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public final override /*1*/ /*fake_override*/ fun name(): kotlin.String @@ -55,7 +55,7 @@ internal final class A { } private constructor E() - public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: A.E): kotlin.Int + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: A.Default.E): kotlin.Int public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public final override /*1*/ /*fake_override*/ fun name(): kotlin.String @@ -63,8 +63,8 @@ internal final class A { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String // Static members - public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): A.E - public final /*synthesized*/ fun values(): kotlin.Array + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): A.Default.E + public final /*synthesized*/ fun values(): kotlin.Array } } } diff --git a/compiler/testData/diagnostics/tests/imports/Imports.txt b/compiler/testData/diagnostics/tests/imports/Imports.txt index bd469c4d99b..19b517e81b1 100644 --- a/compiler/testData/diagnostics/tests/imports/Imports.txt +++ b/compiler/testData/diagnostics/tests/imports/Imports.txt @@ -81,8 +81,8 @@ package c { } package d { - internal val b: d.A.B - internal val c: d.A.B + internal val b: d.A.Default.B + internal val c: d.A.Default.B internal final class A { public constructor A() @@ -103,7 +103,7 @@ package d { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } - internal object C : d.A.B { + internal object C : d.A.Default.B { private constructor C() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int diff --git a/compiler/testData/diagnostics/tests/inner/selfAnnotationForClassObject.txt b/compiler/testData/diagnostics/tests/inner/selfAnnotationForClassObject.txt index ce3ab1010a9..fca99511db7 100644 --- a/compiler/testData/diagnostics/tests/inner/selfAnnotationForClassObject.txt +++ b/compiler/testData/diagnostics/tests/inner/selfAnnotationForClassObject.txt @@ -6,7 +6,7 @@ internal final class Test { public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String - Test.ClassObjectAnnotation() Test.NestedAnnotation() internal class object Default { + Test.Default.ClassObjectAnnotation() Test.NestedAnnotation() internal class object Default { private constructor Default() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateNestedClasses.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateNestedClasses.kt index 8075ccc506a..27221f8e8db 100644 --- a/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateNestedClasses.kt +++ b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateNestedClasses.kt @@ -64,5 +64,5 @@ fun test(m1: M1) { d(m1.d) e(m1.e) f(m1.f) - g(m1.g) + g(m1.g) } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateNestedClasses.txt b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateNestedClasses.txt index a57af5731ce..8edcd908c75 100644 --- a/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateNestedClasses.txt +++ b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateNestedClasses.txt @@ -64,10 +64,10 @@ package p { public final val a: p.A public final val b: p.A.B public final val c: p.A.C - public final val d: p.A.D - public final val e: p.A.D.E + public final val d: p.A.Default.D + public final val e: p.A.Default.D.E public final val f: p.A.F - public final val g: p.A.G + public final val g: p.A.Default.G public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String @@ -82,8 +82,8 @@ package p { public fun a(/*0*/ p: p.A): kotlin.Unit public fun b(/*0*/ p: p.A.B): kotlin.Unit public fun c(/*0*/ p: p.A.C): kotlin.Unit - public fun d(/*0*/ p: p.A.D): kotlin.Unit - public fun e(/*0*/ p: p.A.D.E): kotlin.Unit + public fun d(/*0*/ p: p.A.Default.D): kotlin.Unit + public fun e(/*0*/ p: p.A.Default.D.E): kotlin.Unit public fun f(/*0*/ p: p.A.F): kotlin.Unit public fun g(/*0*/ p: p.A.G): kotlin.Unit @@ -154,8 +154,8 @@ package p { public fun a(/*0*/ p: p.A): kotlin.Unit public fun b(/*0*/ p: p.A.B): kotlin.Unit public fun c(/*0*/ p: p.A.C): kotlin.Unit - public fun d(/*0*/ p: p.A.D): kotlin.Unit - public fun e(/*0*/ p: p.A.D.E): kotlin.Unit + public fun d(/*0*/ p: p.A.Default.D): kotlin.Unit + public fun e(/*0*/ p: p.A.Default.D.E): kotlin.Unit public fun f(/*0*/ p: p.A.F): kotlin.Unit public fun g(/*0*/ p: p.A.G): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/regressions/kt394.txt b/compiler/testData/diagnostics/tests/regressions/kt394.txt index 31453a6ee1a..0d980ab69f5 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt394.txt +++ b/compiler/testData/diagnostics/tests/regressions/kt394.txt @@ -2,7 +2,7 @@ package internal final class X { public constructor X() - internal final val y: X.Y + internal final val y: X.Default.Y public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String diff --git a/compiler/testData/diagnostics/tests/scopes/kt587.txt b/compiler/testData/diagnostics/tests/scopes/kt587.txt index 6f6987cf904..cbc53fd71a9 100644 --- a/compiler/testData/diagnostics/tests/scopes/kt587.txt +++ b/compiler/testData/diagnostics/tests/scopes/kt587.txt @@ -20,7 +20,7 @@ internal final class Main { internal class object Default { private constructor Default() - public final val N: Main.States + public final val N: Main.Default.States public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String diff --git a/compiler/testData/loadJava/compiledKotlin/annotations/classes/AnnotationInClassObject.txt b/compiler/testData/loadJava/compiledKotlin/annotations/classes/AnnotationInClassObject.txt index 05cdc21fc67..8b93de1706e 100644 --- a/compiler/testData/loadJava/compiledKotlin/annotations/classes/AnnotationInClassObject.txt +++ b/compiler/testData/loadJava/compiledKotlin/annotations/classes/AnnotationInClassObject.txt @@ -20,6 +20,6 @@ internal final class A { } } -test.A.Anno1() test.A.B.Anno2() internal final class C { +test.A.Default.Anno1() test.A.Default.B.Anno2() internal final class C { /*primary*/ public constructor C() } diff --git a/compiler/testData/loadJava/compiledKotlin/fromLoadJava/classObjectAnnotation.txt b/compiler/testData/loadJava/compiledKotlin/fromLoadJava/classObjectAnnotation.txt index 3eb84564ffb..2dfae0b1d83 100644 --- a/compiler/testData/loadJava/compiledKotlin/fromLoadJava/classObjectAnnotation.txt +++ b/compiler/testData/loadJava/compiledKotlin/fromLoadJava/classObjectAnnotation.txt @@ -3,7 +3,7 @@ package test internal final class Some { /*primary*/ public constructor Some() - test.Some.TestAnnotation() internal class object Default { + test.Some.Default.TestAnnotation() internal class object Default { /*primary*/ private constructor Default() internal final annotation class TestAnnotation : kotlin.Annotation { diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java index f5552ad97e1..e84ee378e07 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java @@ -104,20 +104,14 @@ public class DescriptorUtils { @NotNull private static FqNameUnsafe getFqNameUnsafe(@NotNull DeclarationDescriptor descriptor) { - DeclarationDescriptor containingDeclaration = getContainingDeclarationSkippingClassObjects(descriptor); + DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); assert containingDeclaration != null : "Not package/module descriptor doesn't have containing declaration: " + descriptor; return getFqName(containingDeclaration).child(descriptor.getName()); } - @Nullable - private static DeclarationDescriptor getContainingDeclarationSkippingClassObjects(@NotNull DeclarationDescriptor descriptor) { - DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); - return isClassObject(containingDeclaration) ? containingDeclaration.getContainingDeclaration() : containingDeclaration; - } - @NotNull public static FqName getFqNameFromTopLevelClass(@NotNull DeclarationDescriptor descriptor) { - DeclarationDescriptor containingDeclaration = getContainingDeclarationSkippingClassObjects(descriptor); + DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); Name name = descriptor.getName(); if (!(containingDeclaration instanceof ClassDescriptor)) { return FqName.topLevel(name); diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt index 520ebb956be..1009964c149 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt @@ -26,7 +26,7 @@ public fun ClassDescriptor.getClassObjectReferenceTarget(): ClassDescriptor = ge public fun DeclarationDescriptor.getImportableDescriptor(): DeclarationDescriptor { return when { - this is ConstructorDescriptor, DescriptorUtils.isClassObject(this) -> getContainingDeclaration()!! + this is ConstructorDescriptor -> getContainingDeclaration() this is PropertyAccessorDescriptor -> getCorrespondingProperty() else -> this } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/util/ImportsUtils.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/util/ImportsUtils.kt index af7f488c238..41d4d0ce2e8 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/util/ImportsUtils.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/util/ImportsUtils.kt @@ -19,16 +19,16 @@ package org.jetbrains.kotlin.idea.imports import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.descriptors.ConstructorDescriptor -import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.descriptors.PackageViewDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.psi.JetSimpleNameExpression import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression import com.intellij.psi.PsiElement import org.jetbrains.kotlin.types.JetType import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.* public val DeclarationDescriptor.importableFqName: FqName? get() { @@ -60,3 +60,12 @@ public fun JetType.canBeReferencedViaImport(): Boolean { val descriptor = getConstructor().getDeclarationDescriptor() return descriptor != null && descriptor.canBeReferencedViaImport() } + +// for cases when class qualifier refers default object treats it like reference to class itself +public fun JetReferenceExpression.getImportableTargets(bindingContext: BindingContext): Collection { + val targets = bindingContext[BindingContext.SHORT_REFERENCE_TO_DEFAULT_OBJECT, this]?.let { listOf(it) } + ?: bindingContext[BindingContext.REFERENCE_TARGET, this]?.let { listOf(it) } + ?: bindingContext[BindingContext.AMBIGUOUS_REFERENCE_TARGET, this] + ?: listOf() + return targets.map { it.getImportableDescriptor() }.toSet() +} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/util/ShortenReferences.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/util/ShortenReferences.kt index edd513b7ab3..b57a68b9710 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/util/ShortenReferences.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/util/ShortenReferences.kt @@ -16,14 +16,11 @@ package org.jetbrains.kotlin.idea.util -import com.intellij.psi.PsiElement; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.psi.*; -import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.renderer.DescriptorRenderer; import com.intellij.psi.util.PsiTreeUtil import com.intellij.openapi.util.TextRange -import com.intellij.psi.PsiDocumentManager import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.analyzer.analyzeInContext import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny @@ -41,6 +38,8 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver import org.jetbrains.kotlin.idea.util.ShortenReferences.Options import org.jetbrains.kotlin.idea.imports.* +import org.jetbrains.kotlin.resolve.* +import com.intellij.psi.* public class ShortenReferences(val options: (JetElement) -> Options = { Options.DEFAULT }) { public data class Options( @@ -51,19 +50,14 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options. val DEFAULT = Options() } } - + class object { val DEFAULT = ShortenReferences() private fun DeclarationDescriptor.asString() = DescriptorRenderer.FQ_NAMES_IN_TYPES.render(this) - private fun JetReferenceExpression.targets(context: BindingContext): Collection { - val targets = context[BindingContext.REFERENCE_TARGET, this]?.let { listOf(it) } - ?: context[BindingContext.AMBIGUOUS_REFERENCE_TARGET, this] - ?: listOf() - return targets.map { it.getImportableDescriptor() }.toSet() - } + private fun JetReferenceExpression.targets(context: BindingContext) = getImportableTargets(context) private fun mayImport(descriptor: DeclarationDescriptor, file: JetFile): Boolean { return descriptor.canBeReferencedViaImport() @@ -152,10 +146,11 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options. while (true) { // Visitor order is important here so that enclosing elements are not shortened before their children are, e.g. // test.foo(this@A) -> foo(this) - val visitors = listOf( + val visitors: List> = listOf( ShortenTypesVisitor(file, elementFilter, failedToImportDescriptors), ShortenThisExpressionsVisitor(file, elementFilter, failedToImportDescriptors), - ShortenQualifiedExpressionsVisitor(file, elementFilter, failedToImportDescriptors) + ShortenQualifiedExpressionsVisitor(file, elementFilter, failedToImportDescriptors), + RemoveExplicitDefaultObjectReferenceVisitor(file, elementFilter, failedToImportDescriptors) ) val descriptorsToImport = visitors.flatMap { analyzeReferences(elementsToUse, it) }.toSet() visitors.forEach { it.shortenElements(elementsToUse) } @@ -201,7 +196,7 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options. protected val failedToImportDescriptors: Set ) : JetVisitorVoid() { var options: Options = Options.DEFAULT - + private val elementsToShorten = ArrayList() private val descriptorsToImport = LinkedHashSet() @@ -209,7 +204,7 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options. protected fun processQualifiedElement(element: T, target: DeclarationDescriptor, canShortenNow: Boolean) { if (canShortenNow) { - elementsToShorten.add(element) + addElementToShorten(element) } else if (target !in failedToImportDescriptors && mayImport(target, file)) { descriptorsToImport.add(target) @@ -219,6 +214,10 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options. } } + protected fun addElementToShorten(element: T) { + elementsToShorten.add(element) + } + protected abstract fun qualifier(element: T): JetElement protected abstract fun shortenElement(element: T): JetElement @@ -257,7 +256,7 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options. if (filterResult == FilterResult.PROCESS) { processType(userType) } - else{ + else { userType.getQualifier()?.accept(this) } } @@ -286,12 +285,11 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options. } } - private class ShortenQualifiedExpressionsVisitor( + private abstract class QualifiedExpressionShorteningVisitor( file: JetFile, elementFilter: (PsiElement) -> FilterResult, failedToImportDescriptors: Set - ) : ShorteningVisitor(file, elementFilter, failedToImportDescriptors) { - + ) : ShorteningVisitor(file, elementFilter, failedToImportDescriptors) { override fun visitDotQualifiedExpression(expression: JetDotQualifiedExpression) { val filterResult = elementFilter(expression) if (filterResult == FilterResult.SKIP) return @@ -305,7 +303,18 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options. expression.getReceiverExpression().accept(this) } - private fun process(qualifiedExpression: JetDotQualifiedExpression): Boolean { + abstract fun process(qualifiedExpression: JetDotQualifiedExpression): Boolean + + override fun qualifier(element: JetDotQualifiedExpression) = element.getReceiverExpression() + } + + private class ShortenQualifiedExpressionsVisitor( + file: JetFile, + elementFilter: (PsiElement) -> FilterResult, + failedToImportDescriptors: Set + ) : QualifiedExpressionShorteningVisitor(file, elementFilter, failedToImportDescriptors) { + + override fun process(qualifiedExpression: JetDotQualifiedExpression): Boolean { val bindingContext = resolutionFacade.analyze(qualifiedExpression) val receiver = qualifiedExpression.getReceiverExpression() @@ -317,7 +326,7 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options. if (bindingContext[BindingContext.QUALIFIER, receiver] == null) return false } } - + if (PsiTreeUtil.getParentOfType( qualifiedExpression, javaClass(), javaClass()) != null) return true @@ -338,10 +347,10 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options. val newCall = selectorCopy.getResolvedCall(newContext) ?: return false val receiverKind = originalCall.getExplicitReceiverKind() val newReceiver = when (receiverKind) { - ExplicitReceiverKind.BOTH_RECEIVERS, ExplicitReceiverKind.EXTENSION_RECEIVER -> newCall.getExtensionReceiver() - ExplicitReceiverKind.DISPATCH_RECEIVER -> newCall.getDispatchReceiver() - else -> return false - } as? ThisReceiver ?: return false + ExplicitReceiverKind.BOTH_RECEIVERS, ExplicitReceiverKind.EXTENSION_RECEIVER -> newCall.getExtensionReceiver() + ExplicitReceiverKind.DISPATCH_RECEIVER -> newCall.getDispatchReceiver() + else -> return false + } as? ThisReceiver ?: return false val thisTarget = receiver.getInstanceReference().targets(bindingContext).singleOrNull() if (newReceiver.getDeclarationDescriptor().asString() != thisTarget?.asString()) return false @@ -356,9 +365,7 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options. return true } - override fun qualifier(element: JetQualifiedExpression) = element.getReceiverExpression() - - override fun shortenElement(element: JetQualifiedExpression): JetElement { + override fun shortenElement(element: JetDotQualifiedExpression): JetElement { return element.replace(element.getSelectorExpression()!!) as JetElement } } @@ -380,7 +387,7 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options. val newContext = simpleThis.analyzeInContext(scope) val targetAfter = simpleThis.getInstanceReference().targets(newContext).singleOrNull() if (targetBefore == targetAfter) { - processQualifiedElement(thisExpression, targetBefore, true) + addElementToShorten(thisExpression) } } @@ -398,6 +405,51 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options. } } + private class RemoveExplicitDefaultObjectReferenceVisitor( + file: JetFile, + elementFilter: (PsiElement) -> FilterResult, + failedToImportDescriptors: Set + ) : QualifiedExpressionShorteningVisitor(file, elementFilter, failedToImportDescriptors) { + + private fun JetExpression.singleTarget(context: BindingContext): DeclarationDescriptor? { + return (getCalleeExpressionIfAny() as? JetReferenceExpression)?.targets(context)?.singleOrNull() + } + + override fun process(qualifiedExpression: JetDotQualifiedExpression): Boolean { + val bindingContext = resolutionFacade.analyze(qualifiedExpression) + + val receiver = qualifiedExpression.getReceiverExpression() + + if (PsiTreeUtil.getParentOfType( + qualifiedExpression, + javaClass(), javaClass()) != null) return false + + val receiverTarget = receiver.singleTarget(bindingContext) ?: return false + if (receiverTarget !is ClassDescriptor) return false + + val selectorExpression = qualifiedExpression.getSelectorExpression() ?: return false + val selectorTarget = selectorExpression.singleTarget(bindingContext) ?: return false + + if (receiverTarget.getDefaultObjectDescriptor() != selectorTarget) return false + + val selectorsSelector = (qualifiedExpression.getParent() as? JetDotQualifiedExpression)?.getSelectorExpression() + if (selectorsSelector == null) { + addElementToShorten(qualifiedExpression) + return true + } + + val selectorsSelectorTarget = selectorsSelector.singleTarget(bindingContext) ?: return false + if (selectorsSelectorTarget is ClassDescriptor) return false + + addElementToShorten(qualifiedExpression) + return true + } + + override fun shortenElement(element: JetDotQualifiedExpression): JetElement { + return element.replace(element.getReceiverExpression()) as JetElement + } + } + // this class is needed to optimize imports only when we actually insert any import (optimization) private class ImportInserter(val file: JetFile) { private var optimizeImports = true diff --git a/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt b/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt index 77495c377c5..1d80ee33be1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt @@ -26,7 +26,6 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.PackageViewDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.formatter.JetCodeStyleSettings import org.jetbrains.kotlin.idea.references.JetReference import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers @@ -36,13 +35,13 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression import org.jetbrains.kotlin.psi.psiUtil.isAncestor -import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils -import org.jetbrains.kotlin.resolve.ImportPath import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension import java.util.ArrayList import java.util.HashMap import java.util.HashSet +import org.jetbrains.kotlin.idea.caches.resolve.* +import org.jetbrains.kotlin.resolve.* public class KotlinImportOptimizer() : ImportOptimizer { @@ -182,12 +181,19 @@ public class KotlinImportOptimizer() : ImportOptimizer { override fun visitPackageDirective(directive: JetPackageDirective) { } + + private fun JetElement.classForDefaultObjectReference(): ClassDescriptor? { + return analyze()[BindingContext.SHORT_REFERENCE_TO_DEFAULT_OBJECT, this as? JetReferenceExpression] + } + override fun visitJetElement(element: JetElement) { val reference = element.getReference() if (reference is JetReference) { val referencedName = (element as? JetNameReferenceExpression)?.getReferencedNameAsName() //TODO: other types of references - val targets = reference.resolveToDescriptors() + //class qualifiers that refer to default objects should be considered (containing) class references + val targets = element.classForDefaultObjectReference()?.let { listOf(it) } + ?: reference.resolveToDescriptors() for (target in targets) { if (!target.canBeReferencedViaImport()) continue if (target is PackageViewDescriptor && target.getFqName().parent() == FqName.ROOT) continue // no need to import top-level packages diff --git a/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt b/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt index 09ecf1b17a5..0574a497c8a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt +++ b/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt @@ -39,8 +39,6 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered import org.jetbrains.kotlin.descriptors.ClassifierDescriptor -import org.jetbrains.kotlin.idea.imports.importableFqName -import org.jetbrains.kotlin.idea.imports.importableFqNameSafe import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.resolve.scopes.JetScope import org.jetbrains.kotlin.descriptors.ModuleDescriptor @@ -54,6 +52,7 @@ import org.jetbrains.kotlin.idea.util.ImportInsertHelper.ImportDescriptorResult import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.idea.refactoring.fqName.isImported import java.util.* +import org.jetbrains.kotlin.idea.imports.* public class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper() { @@ -374,10 +373,7 @@ public class ImportInsertHelperImpl(private val project: Project) : ImportInsert } private fun JetReferenceExpression.resolveTargets(): Collection { - val bindingContext = resolutionFacade.analyze(this, BodyResolveMode.PARTIAL) - return bindingContext[BindingContext.REFERENCE_TARGET, this]?.let { listOf(it) } - ?: bindingContext[BindingContext.AMBIGUOUS_REFERENCE_TARGET, this] - ?: return listOf() + return this.getImportableTargets(resolutionFacade.analyze(this, BodyResolveMode.PARTIAL)) } private fun addImport(fqName: FqName, allUnder: Boolean): JetImportDirective { diff --git a/idea/testData/copyPaste/imports/ClassObject.expected.kt b/idea/testData/copyPaste/imports/ClassObject.expected.kt index d9146d8e4de..bb467d4cf2f 100644 --- a/idea/testData/copyPaste/imports/ClassObject.expected.kt +++ b/idea/testData/copyPaste/imports/ClassObject.expected.kt @@ -7,4 +7,8 @@ import a.T fun g(t: T): Int { g(A) B.f() + A + B + A.Default + B.Default } \ No newline at end of file diff --git a/idea/testData/copyPaste/imports/ClassObject.kt b/idea/testData/copyPaste/imports/ClassObject.kt index 77bcbe0f9a7..945042da459 100644 --- a/idea/testData/copyPaste/imports/ClassObject.kt +++ b/idea/testData/copyPaste/imports/ClassObject.kt @@ -16,6 +16,10 @@ class B { fun g(t: T): Int { g(A) B.f() + A + B + A.Default + B.Default } diff --git a/idea/testData/copyPaste/imports/ClassObjectInner.expected.kt b/idea/testData/copyPaste/imports/ClassObjectInner.expected.kt index 70f5baa69eb..76f3ce9c1c9 100644 --- a/idea/testData/copyPaste/imports/ClassObjectInner.expected.kt +++ b/idea/testData/copyPaste/imports/ClassObjectInner.expected.kt @@ -2,5 +2,5 @@ package to import a.Outer -fun f(i: Outer.Inner, n: Outer.Nested, e: Outer.NestedEnum, o: Outer.NestedObj, t: Outer.NestedTrait, a: Outer.NestedAnnotation) { +fun f(n: Outer.Default.Nested, e: Outer.Default.NestedEnum, o: Outer.Default.NestedObj, t: Outer.Default.NestedTrait, a: Outer.Default.NestedAnnotation) { } \ No newline at end of file diff --git a/idea/testData/copyPaste/imports/ClassObjectInner.kt b/idea/testData/copyPaste/imports/ClassObjectInner.kt index e3dcb57870a..8edb31eeadd 100644 --- a/idea/testData/copyPaste/imports/ClassObjectInner.kt +++ b/idea/testData/copyPaste/imports/ClassObjectInner.kt @@ -1,11 +1,13 @@ package a -import a.Outer.* +import a.Outer.Default.Nested +import a.Outer.Default.NestedEnum +import a.Outer.Default.NestedObj +import a.Outer.Default.NestedTrait +import a.Outer.Default.NestedAnnotation class Outer { class object { - inner class Inner { - } class Nested { } enum class NestedEnum { @@ -18,5 +20,5 @@ class Outer { } } -fun f(i: Inner, n: Nested, e: NestedEnum, o: NestedObj, t: NestedTrait, a: NestedAnnotation) { +fun f(n: Nested, e: NestedEnum, o: NestedObj, t: NestedTrait, a: NestedAnnotation) { } \ No newline at end of file diff --git a/idea/testData/diagnosticMessage/nestedClassShouldBeQualified3.txt b/idea/testData/diagnosticMessage/nestedClassShouldBeQualified3.txt index 5f6d147ef98..4ee0498f173 100644 --- a/idea/testData/diagnosticMessage/nestedClassShouldBeQualified3.txt +++ b/idea/testData/diagnosticMessage/nestedClassShouldBeQualified3.txt @@ -1,2 +1,2 @@ -Nested class 'Nested' should be qualified as 'C.D.Nested' \ No newline at end of file +Nested class 'Nested' should be qualified as 'C.Default.D.Nested' \ No newline at end of file diff --git a/idea/testData/diagnosticMessage/nestedClassShouldBeQualified4.txt b/idea/testData/diagnosticMessage/nestedClassShouldBeQualified4.txt index 2fae93db633..6b0d2a80c71 100644 --- a/idea/testData/diagnosticMessage/nestedClassShouldBeQualified4.txt +++ b/idea/testData/diagnosticMessage/nestedClassShouldBeQualified4.txt @@ -1,2 +1,2 @@ -Nested class 'Nested' should be qualified as 'C.D::Nested' \ No newline at end of file +Nested class 'Nested' should be qualified as 'C.Default.D::Nested' \ No newline at end of file diff --git a/idea/testData/diagnosticMessage/nestedClassShouldBeQualified5.txt b/idea/testData/diagnosticMessage/nestedClassShouldBeQualified5.txt index d662eec3e52..6a7d0009c45 100644 --- a/idea/testData/diagnosticMessage/nestedClassShouldBeQualified5.txt +++ b/idea/testData/diagnosticMessage/nestedClassShouldBeQualified5.txt @@ -1,2 +1,2 @@ -Nested class object of 'F' should be qualified as 'E.F' \ No newline at end of file +Nested class object of 'F' should be qualified as 'E.F.Default' \ No newline at end of file diff --git a/idea/testData/editor/optimizeImports/DefaultObjectReference.dependency.kt b/idea/testData/editor/optimizeImports/DefaultObjectReference.dependency.kt new file mode 100644 index 00000000000..b1ad51eec1b --- /dev/null +++ b/idea/testData/editor/optimizeImports/DefaultObjectReference.dependency.kt @@ -0,0 +1,13 @@ +package d + +class A { + class object E { + val c: Int + } +} + +class B { + class object F { + val c: Int + } +} \ No newline at end of file diff --git a/idea/testData/editor/optimizeImports/DefaultObjectReference.kt b/idea/testData/editor/optimizeImports/DefaultObjectReference.kt new file mode 100644 index 00000000000..d9ea86c295e --- /dev/null +++ b/idea/testData/editor/optimizeImports/DefaultObjectReference.kt @@ -0,0 +1,11 @@ +package p + +import d.A +import d.A.E +import d.B.F +import d.B + +fun main(args: Array) { + F.c + A.c +} \ No newline at end of file diff --git a/idea/testData/editor/optimizeImports/DefaultObjectReference.kt.after b/idea/testData/editor/optimizeImports/DefaultObjectReference.kt.after new file mode 100644 index 00000000000..9fed98bd089 --- /dev/null +++ b/idea/testData/editor/optimizeImports/DefaultObjectReference.kt.after @@ -0,0 +1,9 @@ +package p + +import d.A +import d.B.F + +fun main(args: Array) { + F.c + A.c +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/basic/privateMemberInClassObject.kt.conflicts b/idea/testData/refactoring/extractFunction/basic/privateMemberInClassObject.kt.conflicts index cd10b5c7925..8aabc42af8a 100644 --- a/idea/testData/refactoring/extractFunction/basic/privateMemberInClassObject.kt.conflicts +++ b/idea/testData/refactoring/extractFunction/basic/privateMemberInClassObject.kt.conflicts @@ -1 +1 @@ -Property A.t will become invisible after extraction \ No newline at end of file +Property A.Default.t will become invisible after extraction \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/source/Foo.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/source/Foo.kt index daeab71966c..b44781436e9 100644 --- a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/source/Foo.kt +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/source/Foo.kt @@ -3,5 +3,7 @@ package source import library.* class Bar { - + class object { + val c : Int + } } \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/target/Foo.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/target/Foo.kt index 545ab700bca..493bc989933 100644 --- a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/target/Foo.kt +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/target/Foo.kt @@ -3,6 +3,7 @@ package target import library.JavaClass import library.KtClass import library.KtObject +import source.Bar class Foo { val jv1 = JavaClass.foo() @@ -13,4 +14,11 @@ class Foo { val kt2 = KtObject.foo() val kt3 = KtClass.Inner.foo() val kt4 = KtObject.Inner.foo() + val kt5 = KtClass.foo() + val kt6 = KtClass + val kt7 = KtClass + + val kt8 = Bar + val kt9 = Bar + val kt10 = Bar.c } \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/before/source/Foo.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/before/source/Foo.kt index 53b18972c6b..ef43945e943 100644 --- a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/before/source/Foo.kt +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/before/source/Foo.kt @@ -11,8 +11,17 @@ class Foo { val kt2 = KtObject.foo() val kt3 = KtClass.Inner.foo() val kt4 = KtObject.Inner.foo() + val kt5 = KtClass.Default.foo() + val kt6 = KtClass.Default + val kt7 = KtClass + + val kt8 = Bar + val kt9 = Bar.Default + val kt10 = Bar.Default.c } class Bar { - + class object { + val c : Int + } } \ No newline at end of file diff --git a/idea/testData/shortenRefs/classObject.kt b/idea/testData/shortenRefs/classObject.kt index 6cacac6fee7..013fa3172ef 100644 --- a/idea/testData/shortenRefs/classObject.kt +++ b/idea/testData/shortenRefs/classObject.kt @@ -1,16 +1,34 @@ package p.q -fun foo(): Int { +fun foo(myC: p.q.MyClass, def: p.q.MyClass.Default, nes: p.q.MyClass.Default.Nested) { + p.q.MyClass.Default.foo() + p.q.MyClass.Default.coProp + p.q.MyClass.Default + p.q.MyClass + p.q.MyClass.coProp p.q.MyClass.foo() - return p.q.MyClass.coProp + 10 + p.q.MyClass.bar(p.q.MyClass.Default) + p.q.MyClass.bar(p.q.MyClass) + p.q.MyClass.Default.Nested.Default + p.q.MyClass.Default.Nested.Default.c + MyClass.Default } class MyClass { class object { val coProp = 1 + class Nested { + class object { + val c: Int = 1 + } + } + fun foo() { } + + fun bar(p: MyClass.Default) { + } } } \ No newline at end of file diff --git a/idea/testData/shortenRefs/classObject.kt.after b/idea/testData/shortenRefs/classObject.kt.after index 74dbf912285..5425f4f920b 100644 --- a/idea/testData/shortenRefs/classObject.kt.after +++ b/idea/testData/shortenRefs/classObject.kt.after @@ -1,16 +1,34 @@ package p.q -fun foo(): Int { +fun foo(myC: MyClass, def: MyClass.Default, nes: MyClass.Default.Nested) { MyClass.foo() - return MyClass.coProp + 10 + MyClass.coProp + MyClass + MyClass + MyClass.coProp + MyClass.foo() + MyClass.bar(MyClass) + MyClass.bar(MyClass) + MyClass.Default.Nested + MyClass.Default.Nested.c + MyClass } class MyClass { class object { val coProp = 1 + class Nested { + class object { + val c: Int = 1 + } + } + fun foo() { } + + fun bar(p: MyClass.Default) { + } } } \ 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 0abf001a862..8945a048f70 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/imports/OptimizeImportsTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/imports/OptimizeImportsTestGenerated.java @@ -75,6 +75,12 @@ public class OptimizeImportsTestGenerated extends AbstractOptimizeImportsTest { doTest(fileName); } + @TestMetadata("DefaultObjectReference.kt") + public void testDefaultObjectReference() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/editor/optimizeImports/DefaultObjectReference.kt"); + doTest(fileName); + } + @TestMetadata("DuplicatedImports.kt") public void testDuplicatedImports() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/editor/optimizeImports/DuplicatedImports.kt");