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 =
|
||||
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>>")
|
||||
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();
|
||||
}
|
||||
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)) {
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
@@ -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<A.E> {
|
||||
public enum entry ENTRY : A.E {
|
||||
internal final enum class E : kotlin.Enum<A.Default.E> {
|
||||
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<A.E>
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): A.Default.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 toString(): kotlin.String
|
||||
|
||||
internal final enum class E : kotlin.Enum<A.E> {
|
||||
public enum entry ENTRY2 : A.E {
|
||||
internal final enum class E : kotlin.Enum<A.Default.E> {
|
||||
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<A.E>
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): A.Default.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 toString(): kotlin.String
|
||||
|
||||
internal final enum class E : kotlin.Enum<A.E> {
|
||||
public enum entry ENTRY : A.E {
|
||||
internal final enum class E : kotlin.Enum<A.Default.E> {
|
||||
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<A.E>
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): A.Default.E
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<A.Default.E>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -64,5 +64,5 @@ fun test(m1: M1) {
|
||||
d(m1.d)
|
||||
e(m1.e)
|
||||
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 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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+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()
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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<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
|
||||
|
||||
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<DeclarationDescriptor> {
|
||||
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<ShorteningVisitor<*>> = 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<DeclarationDescriptor>
|
||||
) : JetVisitorVoid() {
|
||||
var options: Options = Options.DEFAULT
|
||||
|
||||
|
||||
private val elementsToShorten = ArrayList<T>()
|
||||
private val descriptorsToImport = LinkedHashSet<DeclarationDescriptor>()
|
||||
|
||||
@@ -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<DeclarationDescriptor>
|
||||
) : ShorteningVisitor<JetQualifiedExpression>(file, elementFilter, failedToImportDescriptors) {
|
||||
|
||||
) : ShorteningVisitor<JetDotQualifiedExpression>(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<DeclarationDescriptor>
|
||||
) : 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<JetImportDirective>(), javaClass<JetPackageDirective>()) != 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<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)
|
||||
private class ImportInserter(val file: JetFile) {
|
||||
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.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
|
||||
|
||||
@@ -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<DeclarationDescriptor> {
|
||||
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 {
|
||||
|
||||
@@ -7,4 +7,8 @@ import a.T
|
||||
fun g(t: T): Int {
|
||||
g(A)
|
||||
B.f()
|
||||
A
|
||||
B
|
||||
A.Default
|
||||
B.Default
|
||||
}
|
||||
@@ -16,6 +16,10 @@ class B {
|
||||
<selection>fun g(t: T): Int {
|
||||
g(A)
|
||||
B.f()
|
||||
A
|
||||
B
|
||||
A.Default
|
||||
B.Default
|
||||
}</selection>
|
||||
|
||||
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
}
|
||||
|
||||
<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>
|
||||
@@ -1,2 +1,2 @@
|
||||
<!-- 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 -->
|
||||
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 -->
|
||||
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.*
|
||||
|
||||
class Bar {
|
||||
|
||||
class object {
|
||||
val c : Int
|
||||
}
|
||||
}
|
||||
+8
@@ -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
|
||||
}
|
||||
+10
-1
@@ -11,8 +11,17 @@ class <caret>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
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,34 @@
|
||||
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()
|
||||
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>
|
||||
|
||||
class MyClass {
|
||||
class object {
|
||||
val coProp = 1
|
||||
|
||||
class Nested {
|
||||
class object {
|
||||
val c: Int = 1
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
|
||||
fun bar(p: MyClass.Default) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user