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()
This commit is contained in:
@@ -96,6 +96,9 @@ public interface BindingContext {
|
|||||||
|
|
||||||
WritableSlice<JetReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET =
|
WritableSlice<JetReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET =
|
||||||
new BasicWritableSlice<JetReferenceExpression, DeclarationDescriptor>(DO_NOTHING);
|
new BasicWritableSlice<JetReferenceExpression, DeclarationDescriptor>(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<JetReferenceExpression, ClassDescriptor> SHORT_REFERENCE_TO_DEFAULT_OBJECT =
|
||||||
|
new BasicWritableSlice<JetReferenceExpression, ClassDescriptor>(DO_NOTHING);
|
||||||
|
|
||||||
@KotlinSignature("val RESOLVED_CALL: WritableSlice<Call, ResolvedCall<out CallableDescriptor>>")
|
@KotlinSignature("val RESOLVED_CALL: WritableSlice<Call, ResolvedCall<out CallableDescriptor>>")
|
||||||
WritableSlice<Call, ResolvedCall<?>> RESOLVED_CALL = new BasicWritableSlice<Call, ResolvedCall<?>>(DO_NOTHING);
|
WritableSlice<Call, ResolvedCall<?>> RESOLVED_CALL = new BasicWritableSlice<Call, ResolvedCall<?>>(DO_NOTHING);
|
||||||
|
|||||||
+5
-1
@@ -58,7 +58,11 @@ public class TracingStrategyImpl extends AbstractTracingStrategy {
|
|||||||
descriptor = ((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall().getCandidateDescriptor();
|
descriptor = ((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall().getCandidateDescriptor();
|
||||||
}
|
}
|
||||||
if (descriptor instanceof FakeCallableDescriptorForObject) {
|
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);
|
DeclarationDescriptor storedReference = trace.get(REFERENCE_TARGET, reference);
|
||||||
if (storedReference == null || !ErrorUtils.isError(descriptor)) {
|
if (storedReference == null || !ErrorUtils.isError(descriptor)) {
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.descriptors.SourceElement
|
|||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getClassObjectReferenceTarget
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getClassObjectReferenceTarget
|
||||||
|
|
||||||
public class FakeCallableDescriptorForObject(
|
public class FakeCallableDescriptorForObject(
|
||||||
private val classDescriptor: ClassDescriptor
|
public val classDescriptor: ClassDescriptor
|
||||||
) : DeclarationDescriptorWithVisibility by classDescriptor.getClassObjectReferenceTarget(), VariableDescriptor {
|
) : DeclarationDescriptorWithVisibility by classDescriptor.getClassObjectReferenceTarget(), VariableDescriptor {
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -148,11 +148,14 @@ private fun QualifierReceiver.resolveAsReceiverInQualifiedExpression(context: Ex
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun QualifierReceiver.resolveAndRecordReferenceTarget(context: ExpressionTypingContext, selector: DeclarationDescriptor?) {
|
private fun QualifierReceiver.resolveAndRecordReferenceTarget(context: ExpressionTypingContext, selector: DeclarationDescriptor?) {
|
||||||
resultingDescriptor = resolveReferenceTarget(selector)
|
resultingDescriptor = resolveReferenceTarget(context, selector)
|
||||||
context.trace.record(REFERENCE_TARGET, referenceExpression, resultingDescriptor)
|
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) {
|
if (classifier is TypeParameterDescriptor) {
|
||||||
return classifier
|
return classifier
|
||||||
}
|
}
|
||||||
@@ -168,6 +171,9 @@ private fun QualifierReceiver.resolveReferenceTarget(selector: DeclarationDescri
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (classifier is ClassDescriptor && classifier.classObjectDescriptor == selectorContainer) {
|
if (classifier is ClassDescriptor && classifier.classObjectDescriptor == selectorContainer) {
|
||||||
|
if (classifier.getDefaultObjectDescriptor() != null) {
|
||||||
|
context.trace.record(SHORT_REFERENCE_TO_DEFAULT_OBJECT, referenceExpression, classifier)
|
||||||
|
}
|
||||||
return classifier.getClassObjectReferenceTarget()
|
return classifier.getClassObjectReferenceTarget()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
package f {
|
package f {
|
||||||
internal fun test(): f.A.B
|
internal fun test(): f.A.Default.B
|
||||||
|
|
||||||
internal final class A {
|
internal final class A {
|
||||||
public constructor A()
|
public constructor A()
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
internal fun f1(): A.B.C.Default
|
internal fun f1(): A.Default.B.C.Default
|
||||||
internal fun f2(): kotlin.Unit
|
internal fun f2(): kotlin.Unit
|
||||||
|
|
||||||
internal final class A {
|
internal final class A {
|
||||||
|
|||||||
@@ -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 hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
internal final enum class E : kotlin.Enum<A.E> {
|
internal final enum class E : kotlin.Enum<A.Default.E> {
|
||||||
public enum entry ENTRY : A.E {
|
public enum entry ENTRY : A.Default.E {
|
||||||
private constructor ENTRY()
|
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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
|
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
|
||||||
@@ -24,7 +24,7 @@ internal final class A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private constructor E()
|
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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
|
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
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
// Static members
|
// Static members
|
||||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): A.E
|
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): A.Default.E
|
||||||
public final /*synthesized*/ fun values(): kotlin.Array<A.E>
|
public final /*synthesized*/ fun values(): kotlin.Array<A.Default.E>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
internal final enum class E : kotlin.Enum<A.E> {
|
internal final enum class E : kotlin.Enum<A.Default.E> {
|
||||||
public enum entry ENTRY2 : A.E {
|
public enum entry ENTRY2 : A.Default.E {
|
||||||
private constructor ENTRY2()
|
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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
|
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
|
||||||
@@ -24,7 +24,7 @@ internal final class A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private constructor E()
|
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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
|
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
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
// Static members
|
// Static members
|
||||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): A.E
|
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): A.Default.E
|
||||||
public final /*synthesized*/ fun values(): kotlin.Array<A.E>
|
public final /*synthesized*/ fun values(): kotlin.Array<A.Default.E>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -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 hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
internal final enum class E : kotlin.Enum<A.E> {
|
internal final enum class E : kotlin.Enum<A.Default.E> {
|
||||||
public enum entry ENTRY : A.E {
|
public enum entry ENTRY : A.Default.E {
|
||||||
private constructor ENTRY()
|
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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
|
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
|
||||||
@@ -55,7 +55,7 @@ internal final class A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private constructor E()
|
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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
|
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
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
// Static members
|
// Static members
|
||||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): A.E
|
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): A.Default.E
|
||||||
public final /*synthesized*/ fun values(): kotlin.Array<A.E>
|
public final /*synthesized*/ fun values(): kotlin.Array<A.Default.E>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,8 +81,8 @@ package c {
|
|||||||
}
|
}
|
||||||
|
|
||||||
package d {
|
package d {
|
||||||
internal val b: d.A.B
|
internal val b: d.A.Default.B
|
||||||
internal val c: d.A.B
|
internal val c: d.A.Default.B
|
||||||
|
|
||||||
internal final class A {
|
internal final class A {
|
||||||
public constructor A()
|
public constructor A()
|
||||||
@@ -103,7 +103,7 @@ package d {
|
|||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
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()
|
private constructor C()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
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 hashCode(): kotlin.Int
|
||||||
|
|||||||
@@ -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 hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
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()
|
private constructor Default()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
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 hashCode(): kotlin.Int
|
||||||
|
|||||||
+1
-1
@@ -64,5 +64,5 @@ fun test(m1: M1) {
|
|||||||
d(m1.d)
|
d(m1.d)
|
||||||
e(m1.e)
|
e(m1.e)
|
||||||
f(m1.f)
|
f(m1.f)
|
||||||
g(m1.g)
|
g(<!TYPE_MISMATCH!>m1.g<!>)
|
||||||
}
|
}
|
||||||
+7
-7
@@ -64,10 +64,10 @@ package p {
|
|||||||
public final val a: p.A
|
public final val a: p.A
|
||||||
public final val b: p.A.B
|
public final val b: p.A.B
|
||||||
public final val c: p.A.C
|
public final val c: p.A.C
|
||||||
public final val d: p.A.D
|
public final val d: p.A.Default.D
|
||||||
public final val e: p.A.D.E
|
public final val e: p.A.Default.D.E
|
||||||
public final val f: p.A.F
|
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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
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 a(/*0*/ p: p.A): kotlin.Unit
|
||||||
public fun b(/*0*/ p: p.A.B): kotlin.Unit
|
public fun b(/*0*/ p: p.A.B): kotlin.Unit
|
||||||
public fun c(/*0*/ p: p.A.C): kotlin.Unit
|
public fun c(/*0*/ p: p.A.C): kotlin.Unit
|
||||||
public fun d(/*0*/ p: p.A.D): kotlin.Unit
|
public fun d(/*0*/ p: p.A.Default.D): kotlin.Unit
|
||||||
public fun e(/*0*/ p: p.A.D.E): 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 f(/*0*/ p: p.A.F): kotlin.Unit
|
||||||
public fun g(/*0*/ p: p.A.G): 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 a(/*0*/ p: p.A): kotlin.Unit
|
||||||
public fun b(/*0*/ p: p.A.B): kotlin.Unit
|
public fun b(/*0*/ p: p.A.B): kotlin.Unit
|
||||||
public fun c(/*0*/ p: p.A.C): kotlin.Unit
|
public fun c(/*0*/ p: p.A.C): kotlin.Unit
|
||||||
public fun d(/*0*/ p: p.A.D): kotlin.Unit
|
public fun d(/*0*/ p: p.A.Default.D): kotlin.Unit
|
||||||
public fun e(/*0*/ p: p.A.D.E): 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 f(/*0*/ p: p.A.F): kotlin.Unit
|
||||||
public fun g(/*0*/ p: p.A.G): kotlin.Unit
|
public fun g(/*0*/ p: p.A.G): kotlin.Unit
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package
|
|||||||
|
|
||||||
internal final class X {
|
internal final class X {
|
||||||
public constructor 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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ internal final class Main {
|
|||||||
|
|
||||||
internal class object Default {
|
internal class object Default {
|
||||||
private constructor 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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|||||||
+1
-1
@@ -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()
|
/*primary*/ public constructor C()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package test
|
|||||||
internal final class Some {
|
internal final class Some {
|
||||||
/*primary*/ public constructor Some()
|
/*primary*/ public constructor Some()
|
||||||
|
|
||||||
test.Some.TestAnnotation() internal class object Default {
|
test.Some.Default.TestAnnotation() internal class object Default {
|
||||||
/*primary*/ private constructor Default()
|
/*primary*/ private constructor Default()
|
||||||
|
|
||||||
internal final annotation class TestAnnotation : kotlin.Annotation {
|
internal final annotation class TestAnnotation : kotlin.Annotation {
|
||||||
|
|||||||
@@ -104,20 +104,14 @@ public class DescriptorUtils {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static FqNameUnsafe getFqNameUnsafe(@NotNull DeclarationDescriptor descriptor) {
|
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;
|
assert containingDeclaration != null : "Not package/module descriptor doesn't have containing declaration: " + descriptor;
|
||||||
return getFqName(containingDeclaration).child(descriptor.getName());
|
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
|
@NotNull
|
||||||
public static FqName getFqNameFromTopLevelClass(@NotNull DeclarationDescriptor descriptor) {
|
public static FqName getFqNameFromTopLevelClass(@NotNull DeclarationDescriptor descriptor) {
|
||||||
DeclarationDescriptor containingDeclaration = getContainingDeclarationSkippingClassObjects(descriptor);
|
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||||
Name name = descriptor.getName();
|
Name name = descriptor.getName();
|
||||||
if (!(containingDeclaration instanceof ClassDescriptor)) {
|
if (!(containingDeclaration instanceof ClassDescriptor)) {
|
||||||
return FqName.topLevel(name);
|
return FqName.topLevel(name);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public fun ClassDescriptor.getClassObjectReferenceTarget(): ClassDescriptor = ge
|
|||||||
|
|
||||||
public fun DeclarationDescriptor.getImportableDescriptor(): DeclarationDescriptor {
|
public fun DeclarationDescriptor.getImportableDescriptor(): DeclarationDescriptor {
|
||||||
return when {
|
return when {
|
||||||
this is ConstructorDescriptor, DescriptorUtils.isClassObject(this) -> getContainingDeclaration()!!
|
this is ConstructorDescriptor -> getContainingDeclaration()
|
||||||
this is PropertyAccessorDescriptor -> getCorrespondingProperty()
|
this is PropertyAccessorDescriptor -> getCorrespondingProperty()
|
||||||
else -> this
|
else -> this
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,16 +19,16 @@ package org.jetbrains.kotlin.idea.imports
|
|||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|
||||||
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
|
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
|
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.types.JetType
|
import org.jetbrains.kotlin.types.JetType
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.resolve.*
|
||||||
|
|
||||||
public val DeclarationDescriptor.importableFqName: FqName?
|
public val DeclarationDescriptor.importableFqName: FqName?
|
||||||
get() {
|
get() {
|
||||||
@@ -60,3 +60,12 @@ public fun JetType.canBeReferencedViaImport(): Boolean {
|
|||||||
val descriptor = getConstructor().getDeclarationDescriptor()
|
val descriptor = getConstructor().getDeclarationDescriptor()
|
||||||
return descriptor != null && descriptor.canBeReferencedViaImport()
|
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<DeclarationDescriptor> {
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,14 +16,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.util
|
package org.jetbrains.kotlin.idea.util
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.PsiDocumentManager
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.analyzer.analyzeInContext
|
import org.jetbrains.kotlin.analyzer.analyzeInContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
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.resolve.scopes.receivers.ThisReceiver
|
||||||
import org.jetbrains.kotlin.idea.util.ShortenReferences.Options
|
import org.jetbrains.kotlin.idea.util.ShortenReferences.Options
|
||||||
import org.jetbrains.kotlin.idea.imports.*
|
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 class ShortenReferences(val options: (JetElement) -> Options = { Options.DEFAULT }) {
|
||||||
public data class Options(
|
public data class Options(
|
||||||
@@ -58,12 +57,7 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options.
|
|||||||
private fun DeclarationDescriptor.asString()
|
private fun DeclarationDescriptor.asString()
|
||||||
= DescriptorRenderer.FQ_NAMES_IN_TYPES.render(this)
|
= DescriptorRenderer.FQ_NAMES_IN_TYPES.render(this)
|
||||||
|
|
||||||
private fun JetReferenceExpression.targets(context: BindingContext): Collection<DeclarationDescriptor> {
|
private fun JetReferenceExpression.targets(context: BindingContext) = getImportableTargets(context)
|
||||||
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 mayImport(descriptor: DeclarationDescriptor, file: JetFile): Boolean {
|
private fun mayImport(descriptor: DeclarationDescriptor, file: JetFile): Boolean {
|
||||||
return descriptor.canBeReferencedViaImport()
|
return descriptor.canBeReferencedViaImport()
|
||||||
@@ -152,10 +146,11 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options.
|
|||||||
while (true) {
|
while (true) {
|
||||||
// Visitor order is important here so that enclosing elements are not shortened before their children are, e.g.
|
// Visitor order is important here so that enclosing elements are not shortened before their children are, e.g.
|
||||||
// test.foo(this@A) -> foo(this)
|
// test.foo(this@A) -> foo(this)
|
||||||
val visitors = listOf(
|
val visitors: List<ShorteningVisitor<*>> = listOf(
|
||||||
ShortenTypesVisitor(file, elementFilter, failedToImportDescriptors),
|
ShortenTypesVisitor(file, elementFilter, failedToImportDescriptors),
|
||||||
ShortenThisExpressionsVisitor(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()
|
val descriptorsToImport = visitors.flatMap { analyzeReferences(elementsToUse, it) }.toSet()
|
||||||
visitors.forEach { it.shortenElements(elementsToUse) }
|
visitors.forEach { it.shortenElements(elementsToUse) }
|
||||||
@@ -209,7 +204,7 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options.
|
|||||||
|
|
||||||
protected fun processQualifiedElement(element: T, target: DeclarationDescriptor, canShortenNow: Boolean) {
|
protected fun processQualifiedElement(element: T, target: DeclarationDescriptor, canShortenNow: Boolean) {
|
||||||
if (canShortenNow) {
|
if (canShortenNow) {
|
||||||
elementsToShorten.add(element)
|
addElementToShorten(element)
|
||||||
}
|
}
|
||||||
else if (target !in failedToImportDescriptors && mayImport(target, file)) {
|
else if (target !in failedToImportDescriptors && mayImport(target, file)) {
|
||||||
descriptorsToImport.add(target)
|
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 qualifier(element: T): JetElement
|
||||||
|
|
||||||
protected abstract fun shortenElement(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) {
|
if (filterResult == FilterResult.PROCESS) {
|
||||||
processType(userType)
|
processType(userType)
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
userType.getQualifier()?.accept(this)
|
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,
|
file: JetFile,
|
||||||
elementFilter: (PsiElement) -> FilterResult,
|
elementFilter: (PsiElement) -> FilterResult,
|
||||||
failedToImportDescriptors: Set<DeclarationDescriptor>
|
failedToImportDescriptors: Set<DeclarationDescriptor>
|
||||||
) : ShorteningVisitor<JetQualifiedExpression>(file, elementFilter, failedToImportDescriptors) {
|
) : ShorteningVisitor<JetDotQualifiedExpression>(file, elementFilter, failedToImportDescriptors) {
|
||||||
|
|
||||||
override fun visitDotQualifiedExpression(expression: JetDotQualifiedExpression) {
|
override fun visitDotQualifiedExpression(expression: JetDotQualifiedExpression) {
|
||||||
val filterResult = elementFilter(expression)
|
val filterResult = elementFilter(expression)
|
||||||
if (filterResult == FilterResult.SKIP) return
|
if (filterResult == FilterResult.SKIP) return
|
||||||
@@ -305,7 +303,18 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options.
|
|||||||
expression.getReceiverExpression().accept(this)
|
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<DeclarationDescriptor>
|
||||||
|
) : QualifiedExpressionShorteningVisitor(file, elementFilter, failedToImportDescriptors) {
|
||||||
|
|
||||||
|
override fun process(qualifiedExpression: JetDotQualifiedExpression): Boolean {
|
||||||
val bindingContext = resolutionFacade.analyze(qualifiedExpression)
|
val bindingContext = resolutionFacade.analyze(qualifiedExpression)
|
||||||
|
|
||||||
val receiver = qualifiedExpression.getReceiverExpression()
|
val receiver = qualifiedExpression.getReceiverExpression()
|
||||||
@@ -338,10 +347,10 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options.
|
|||||||
val newCall = selectorCopy.getResolvedCall(newContext) ?: return false
|
val newCall = selectorCopy.getResolvedCall(newContext) ?: return false
|
||||||
val receiverKind = originalCall.getExplicitReceiverKind()
|
val receiverKind = originalCall.getExplicitReceiverKind()
|
||||||
val newReceiver = when (receiverKind) {
|
val newReceiver = when (receiverKind) {
|
||||||
ExplicitReceiverKind.BOTH_RECEIVERS, ExplicitReceiverKind.EXTENSION_RECEIVER -> newCall.getExtensionReceiver()
|
ExplicitReceiverKind.BOTH_RECEIVERS, ExplicitReceiverKind.EXTENSION_RECEIVER -> newCall.getExtensionReceiver()
|
||||||
ExplicitReceiverKind.DISPATCH_RECEIVER -> newCall.getDispatchReceiver()
|
ExplicitReceiverKind.DISPATCH_RECEIVER -> newCall.getDispatchReceiver()
|
||||||
else -> return false
|
else -> return false
|
||||||
} as? ThisReceiver ?: return false
|
} as? ThisReceiver ?: return false
|
||||||
|
|
||||||
val thisTarget = receiver.getInstanceReference().targets(bindingContext).singleOrNull()
|
val thisTarget = receiver.getInstanceReference().targets(bindingContext).singleOrNull()
|
||||||
if (newReceiver.getDeclarationDescriptor().asString() != thisTarget?.asString()) return false
|
if (newReceiver.getDeclarationDescriptor().asString() != thisTarget?.asString()) return false
|
||||||
@@ -356,9 +365,7 @@ public class ShortenReferences(val options: (JetElement) -> Options = { Options.
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun qualifier(element: JetQualifiedExpression) = element.getReceiverExpression()
|
override fun shortenElement(element: JetDotQualifiedExpression): JetElement {
|
||||||
|
|
||||||
override fun shortenElement(element: JetQualifiedExpression): JetElement {
|
|
||||||
return element.replace(element.getSelectorExpression()!!) as 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 newContext = simpleThis.analyzeInContext(scope)
|
||||||
val targetAfter = simpleThis.getInstanceReference().targets(newContext).singleOrNull()
|
val targetAfter = simpleThis.getInstanceReference().targets(newContext).singleOrNull()
|
||||||
if (targetBefore == targetAfter) {
|
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<DeclarationDescriptor>
|
||||||
|
) : 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<JetImportDirective>(), javaClass<JetPackageDirective>()) != 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)
|
// this class is needed to optimize imports only when we actually insert any import (optimization)
|
||||||
private class ImportInserter(val file: JetFile) {
|
private class ImportInserter(val file: JetFile) {
|
||||||
private var optimizeImports = true
|
private var optimizeImports = true
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
|
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.formatter.JetCodeStyleSettings
|
||||||
import org.jetbrains.kotlin.idea.references.JetReference
|
import org.jetbrains.kotlin.idea.references.JetReference
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
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.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
|
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
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.getImportableDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
import java.util.HashSet
|
import java.util.HashSet
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.*
|
||||||
|
import org.jetbrains.kotlin.resolve.*
|
||||||
|
|
||||||
public class KotlinImportOptimizer() : ImportOptimizer {
|
public class KotlinImportOptimizer() : ImportOptimizer {
|
||||||
|
|
||||||
@@ -182,12 +181,19 @@ public class KotlinImportOptimizer() : ImportOptimizer {
|
|||||||
override fun visitPackageDirective(directive: JetPackageDirective) {
|
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) {
|
override fun visitJetElement(element: JetElement) {
|
||||||
val reference = element.getReference()
|
val reference = element.getReference()
|
||||||
if (reference is JetReference) {
|
if (reference is JetReference) {
|
||||||
val referencedName = (element as? JetNameReferenceExpression)?.getReferencedNameAsName() //TODO: other types of references
|
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) {
|
for (target in targets) {
|
||||||
if (!target.canBeReferencedViaImport()) continue
|
if (!target.canBeReferencedViaImport()) continue
|
||||||
if (target is PackageViewDescriptor && target.getFqName().parent() == FqName.ROOT) continue // no need to import top-level packages
|
if (target is PackageViewDescriptor && target.getFqName().parent() == FqName.ROOT) continue // no need to import top-level packages
|
||||||
|
|||||||
@@ -39,8 +39,6 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
|||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
||||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
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.utils.addIfNotNull
|
||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
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.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.idea.refactoring.fqName.isImported
|
import org.jetbrains.kotlin.idea.refactoring.fqName.isImported
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import org.jetbrains.kotlin.idea.imports.*
|
||||||
|
|
||||||
public class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper() {
|
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<DeclarationDescriptor> {
|
private fun JetReferenceExpression.resolveTargets(): Collection<DeclarationDescriptor> {
|
||||||
val bindingContext = resolutionFacade.analyze(this, BodyResolveMode.PARTIAL)
|
return this.getImportableTargets(resolutionFacade.analyze(this, BodyResolveMode.PARTIAL))
|
||||||
return bindingContext[BindingContext.REFERENCE_TARGET, this]?.let { listOf(it) }
|
|
||||||
?: bindingContext[BindingContext.AMBIGUOUS_REFERENCE_TARGET, this]
|
|
||||||
?: return listOf()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addImport(fqName: FqName, allUnder: Boolean): JetImportDirective {
|
private fun addImport(fqName: FqName, allUnder: Boolean): JetImportDirective {
|
||||||
|
|||||||
@@ -7,4 +7,8 @@ import a.T
|
|||||||
fun g(t: T): Int {
|
fun g(t: T): Int {
|
||||||
g(A)
|
g(A)
|
||||||
B.f()
|
B.f()
|
||||||
|
A
|
||||||
|
B
|
||||||
|
A.Default
|
||||||
|
B.Default
|
||||||
}
|
}
|
||||||
@@ -16,6 +16,10 @@ class B {
|
|||||||
<selection>fun g(t: T): Int {
|
<selection>fun g(t: T): Int {
|
||||||
g(A)
|
g(A)
|
||||||
B.f()
|
B.f()
|
||||||
|
A
|
||||||
|
B
|
||||||
|
A.Default
|
||||||
|
B.Default
|
||||||
}</selection>
|
}</selection>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ package to
|
|||||||
|
|
||||||
import a.Outer
|
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) {
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
package a
|
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 Outer {
|
||||||
class object {
|
class object {
|
||||||
inner class Inner {
|
|
||||||
}
|
|
||||||
class Nested {
|
class Nested {
|
||||||
}
|
}
|
||||||
enum class NestedEnum {
|
enum class NestedEnum {
|
||||||
@@ -18,5 +20,5 @@ class Outer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<selection>fun f(i: Inner, n: Nested, e: NestedEnum, o: NestedObj, t: NestedTrait, a: NestedAnnotation) {
|
<selection>fun f(n: Nested, e: NestedEnum, o: NestedObj, t: NestedTrait, a: NestedAnnotation) {
|
||||||
}</selection>
|
}</selection>
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
<!-- nestedClassShouldBeQualified3 -->
|
<!-- nestedClassShouldBeQualified3 -->
|
||||||
Nested class 'Nested' should be qualified as 'C.D.Nested'
|
Nested class 'Nested' should be qualified as 'C.Default.D.Nested'
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
<!-- nestedClassShouldBeQualified4 -->
|
<!-- nestedClassShouldBeQualified4 -->
|
||||||
Nested class 'Nested' should be qualified as 'C.D::Nested'
|
Nested class 'Nested' should be qualified as 'C.Default.D::Nested'
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
<!-- nestedClassShouldBeQualified5 -->
|
<!-- nestedClassShouldBeQualified5 -->
|
||||||
Nested class object of 'F' should be qualified as 'E.F'
|
Nested class object of 'F' should be qualified as 'E.F.Default'
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package d
|
||||||
|
|
||||||
|
class A {
|
||||||
|
class object E {
|
||||||
|
val c: Int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
class object F {
|
||||||
|
val c: Int
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package p
|
||||||
|
|
||||||
|
import d.A
|
||||||
|
import d.A.E
|
||||||
|
import d.B.F
|
||||||
|
import d.B
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
F.c
|
||||||
|
A.c
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package p
|
||||||
|
|
||||||
|
import d.A
|
||||||
|
import d.B.F
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
F.c
|
||||||
|
A.c
|
||||||
|
}
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
Property A.t will become invisible after extraction
|
Property A.Default.t will become invisible after extraction
|
||||||
+3
-1
@@ -3,5 +3,7 @@ package source
|
|||||||
import library.*
|
import library.*
|
||||||
|
|
||||||
class Bar {
|
class Bar {
|
||||||
|
class object {
|
||||||
|
val c : Int
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+8
@@ -3,6 +3,7 @@ package target
|
|||||||
import library.JavaClass
|
import library.JavaClass
|
||||||
import library.KtClass
|
import library.KtClass
|
||||||
import library.KtObject
|
import library.KtObject
|
||||||
|
import source.Bar
|
||||||
|
|
||||||
class Foo {
|
class Foo {
|
||||||
val jv1 = JavaClass.foo()
|
val jv1 = JavaClass.foo()
|
||||||
@@ -13,4 +14,11 @@ class Foo {
|
|||||||
val kt2 = KtObject.foo()
|
val kt2 = KtObject.foo()
|
||||||
val kt3 = KtClass.Inner.foo()
|
val kt3 = KtClass.Inner.foo()
|
||||||
val kt4 = KtObject.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
|
||||||
}
|
}
|
||||||
+10
-1
@@ -11,8 +11,17 @@ class <caret>Foo {
|
|||||||
val kt2 = KtObject.foo()
|
val kt2 = KtObject.foo()
|
||||||
val kt3 = KtClass.Inner.foo()
|
val kt3 = KtClass.Inner.foo()
|
||||||
val kt4 = KtObject.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 Bar {
|
||||||
|
class object {
|
||||||
|
val c : Int
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,34 @@
|
|||||||
package p.q
|
package p.q
|
||||||
|
|
||||||
<selection>fun foo(): Int {
|
<selection>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()
|
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
|
||||||
}</selection>
|
}</selection>
|
||||||
|
|
||||||
class MyClass {
|
class MyClass {
|
||||||
class object {
|
class object {
|
||||||
val coProp = 1
|
val coProp = 1
|
||||||
|
|
||||||
|
class Nested {
|
||||||
|
class object {
|
||||||
|
val c: Int = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun bar(p: MyClass.Default) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,34 @@
|
|||||||
package p.q
|
package p.q
|
||||||
|
|
||||||
fun foo(): Int {
|
fun foo(myC: MyClass, def: MyClass.Default, nes: MyClass.Default.Nested) {
|
||||||
MyClass.foo()
|
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 MyClass {
|
||||||
class object {
|
class object {
|
||||||
val coProp = 1
|
val coProp = 1
|
||||||
|
|
||||||
|
class Nested {
|
||||||
|
class object {
|
||||||
|
val c: Int = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun bar(p: MyClass.Default) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,6 +75,12 @@ public class OptimizeImportsTestGenerated extends AbstractOptimizeImportsTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("DuplicatedImports.kt")
|
||||||
public void testDuplicatedImports() throws Exception {
|
public void testDuplicatedImports() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/editor/optimizeImports/DuplicatedImports.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/editor/optimizeImports/DuplicatedImports.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user