changed local extensions priority
local extensions aren't longer chosen before members
This commit is contained in:
+4
-31
@@ -36,9 +36,7 @@ public class ResolutionTaskHolder<D extends CallableDescriptor, F extends D> {
|
||||
private final PriorityProvider<ResolutionCandidate<D>> priorityProvider;
|
||||
private final boolean isSafeCall;
|
||||
|
||||
private final Collection<Collection<ResolutionCandidate<D>>> localExtensions = Sets.newLinkedHashSet();
|
||||
private final Collection<Collection<ResolutionCandidate<D>>> members = Sets.newLinkedHashSet();
|
||||
private final Collection<Collection<ResolutionCandidate<D>>> nonLocalExtensions = Sets.newLinkedHashSet();
|
||||
private final Collection<Collection<ResolutionCandidate<D>>> candidatesList = Lists.newArrayList();
|
||||
|
||||
private List<ResolutionTask<D, F>> tasks = null;
|
||||
|
||||
@@ -59,44 +57,19 @@ public class ResolutionTaskHolder<D extends CallableDescriptor, F extends D> {
|
||||
return candidates;
|
||||
}
|
||||
|
||||
public void addLocalExtensions(@NotNull Collection<ResolutionCandidate<D>> candidates) {
|
||||
public void addCandidates(@NotNull Collection<ResolutionCandidate<D>> candidates) {
|
||||
if (!candidates.isEmpty()) {
|
||||
localExtensions.add(setIsSafeCall(candidates));
|
||||
}
|
||||
}
|
||||
|
||||
public void addMembers(@NotNull Collection<ResolutionCandidate<D>> candidates) {
|
||||
if (!candidates.isEmpty()) {
|
||||
members.add(setIsSafeCall(candidates));
|
||||
}
|
||||
}
|
||||
|
||||
public void addNonLocalExtensions(@NotNull Collection<ResolutionCandidate<D>> candidates) {
|
||||
if (!candidates.isEmpty()) {
|
||||
nonLocalExtensions.add(setIsSafeCall(candidates));
|
||||
candidatesList.add(setIsSafeCall(candidates));
|
||||
}
|
||||
}
|
||||
|
||||
public List<ResolutionTask<D, F>> getTasks() {
|
||||
if (tasks == null) {
|
||||
tasks = Lists.newArrayList();
|
||||
List<Collection<ResolutionCandidate<D>>> candidateList = Lists.newArrayList();
|
||||
// If the call is of the form super.foo(), it can actually be only a member
|
||||
// But if there's no appropriate member, we would like to report that super cannot be a receiver for an extension
|
||||
// Thus, put members first
|
||||
if (TaskPrioritizer.getReceiverSuper(basicCallResolutionContext.call.getExplicitReceiver()) != null) {
|
||||
candidateList.addAll(members);
|
||||
candidateList.addAll(localExtensions);
|
||||
}
|
||||
else {
|
||||
candidateList.addAll(localExtensions);
|
||||
candidateList.addAll(members);
|
||||
}
|
||||
candidateList.addAll(nonLocalExtensions);
|
||||
|
||||
for (int priority = priorityProvider.getMaxPriority(); priority >= 0; priority--) {
|
||||
final int finalPriority = priority;
|
||||
for (Collection<ResolutionCandidate<D>> candidates : candidateList) {
|
||||
for (Collection<ResolutionCandidate<D>> candidates : candidatesList) {
|
||||
Collection<ResolutionCandidate<D>> filteredCandidates = Collections2.filter(candidates, new Predicate<ResolutionCandidate<D>>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable ResolutionCandidate<D> input) {
|
||||
|
||||
+10
-13
@@ -147,29 +147,26 @@ public class TaskPrioritizer {
|
||||
if (receiver.exists()) {
|
||||
List<ReceiverValue> variantsForExplicitReceiver = autoCastService.getVariantsForReceiver(receiver);
|
||||
|
||||
Collection<ResolutionCandidate<D>> extensionFunctions = convertWithImpliedThis(scope, variantsForExplicitReceiver, callableDescriptorCollector.getNonMembersByName(scope, name));
|
||||
List<ResolutionCandidate<D>> nonlocals = Lists.newArrayList();
|
||||
List<ResolutionCandidate<D>> locals = Lists.newArrayList();
|
||||
//noinspection unchecked,RedundantTypeArguments
|
||||
TaskPrioritizer.<D>splitLexicallyLocalDescriptors(extensionFunctions, scope.getContainingDeclaration(), locals, nonlocals);
|
||||
|
||||
Collection<ResolutionCandidate<D>> members = Lists.newArrayList();
|
||||
for (ReceiverValue variant : variantsForExplicitReceiver) {
|
||||
Collection<? extends D> membersForThisVariant = callableDescriptorCollector.getMembersByName(variant.getType(), name);
|
||||
convertWithReceivers(membersForThisVariant, Collections.singletonList(variant), Collections.singletonList(NO_RECEIVER), members, hasExplicitThisObject);
|
||||
convertWithReceivers(membersForThisVariant, Collections.singletonList(variant),
|
||||
Collections.singletonList(NO_RECEIVER), members, hasExplicitThisObject);
|
||||
}
|
||||
|
||||
result.addLocalExtensions(locals);
|
||||
result.addMembers(members);
|
||||
result.addCandidates(members);
|
||||
|
||||
for (ReceiverValue implicitReceiver : implicitReceivers) {
|
||||
Collection<? extends D> memberExtensions = callableDescriptorCollector.getNonMembersByName(
|
||||
implicitReceiver.getType().getMemberScope(), name);
|
||||
List<ReceiverValue> variantsForImplicitReceiver = autoCastService.getVariantsForReceiver(implicitReceiver);
|
||||
result.addNonLocalExtensions(convertWithReceivers(memberExtensions, variantsForImplicitReceiver, variantsForExplicitReceiver, hasExplicitThisObject));
|
||||
result.addCandidates(convertWithReceivers(memberExtensions, variantsForImplicitReceiver,
|
||||
variantsForExplicitReceiver, hasExplicitThisObject));
|
||||
}
|
||||
|
||||
result.addNonLocalExtensions(nonlocals);
|
||||
Collection<ResolutionCandidate<D>> extensionFunctions = convertWithImpliedThis(
|
||||
scope, variantsForExplicitReceiver, callableDescriptorCollector.getNonMembersByName(scope, name));
|
||||
result.addCandidates(extensionFunctions);
|
||||
}
|
||||
else {
|
||||
Collection<ResolutionCandidate<D>> functions = convertWithImpliedThis(scope, Collections.singletonList(receiver), callableDescriptorCollector
|
||||
@@ -180,12 +177,12 @@ public class TaskPrioritizer {
|
||||
//noinspection unchecked,RedundantTypeArguments
|
||||
TaskPrioritizer.<D>splitLexicallyLocalDescriptors(functions, scope.getContainingDeclaration(), locals, nonlocals);
|
||||
|
||||
result.addLocalExtensions(locals);
|
||||
result.addCandidates(locals);
|
||||
|
||||
for (ReceiverValue implicitReceiver : implicitReceivers) {
|
||||
doComputeTasks(scope, implicitReceiver, name, result, context, callableDescriptorCollector);
|
||||
}
|
||||
result.addNonLocalExtensions(nonlocals);
|
||||
result.addCandidates(nonlocals);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
fun box() : String {
|
||||
if (!B().test()) return "fail 1";
|
||||
if (!D().test()) return "fail 2"
|
||||
if (!F().test()) return "fail 3"
|
||||
if (!L().test()) return "fail 4"
|
||||
if (!H().test()) return "fail 5"
|
||||
if (!N().test()) return "fail 6"
|
||||
return "OK"
|
||||
}
|
||||
|
||||
class A {
|
||||
fun foo() = 1
|
||||
}
|
||||
|
||||
class B {
|
||||
fun foo() = 2
|
||||
|
||||
fun A.bar() = foo()
|
||||
|
||||
fun test() = A().bar() == 1
|
||||
}
|
||||
|
||||
|
||||
class C {
|
||||
fun D.foo() = 2
|
||||
}
|
||||
|
||||
class D {
|
||||
fun C.foo() = 1
|
||||
|
||||
fun C.bar() = foo()
|
||||
|
||||
fun test() = C().bar() == 1
|
||||
}
|
||||
|
||||
class E
|
||||
fun E.foo() = 2
|
||||
|
||||
class F {
|
||||
fun foo() = 1
|
||||
|
||||
fun E.bar() = foo()
|
||||
|
||||
fun test() = E().bar() == 1
|
||||
}
|
||||
|
||||
class G
|
||||
fun G.foo() = 2
|
||||
|
||||
class H {
|
||||
fun G.foo() = 1
|
||||
|
||||
fun G.bar() = foo()
|
||||
|
||||
fun test() = G().bar() == 1
|
||||
}
|
||||
|
||||
class K
|
||||
class L {
|
||||
fun K.bar() = foo()
|
||||
|
||||
fun test() = K().bar() == 1
|
||||
}
|
||||
fun K.foo() = 1
|
||||
fun L.foo() = 2
|
||||
|
||||
class M
|
||||
class N {
|
||||
fun foo() = 1
|
||||
fun M.foo() = 2
|
||||
|
||||
fun M.bar() = foo()
|
||||
|
||||
fun test() = M().bar() == 1
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class A {
|
||||
fun B.foo() = 2
|
||||
}
|
||||
|
||||
class B {
|
||||
~A.foo~fun A.foo() = 1
|
||||
|
||||
fun A.bar() = `A.foo`foo()
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class A
|
||||
|
||||
class B {
|
||||
fun A.bar() = `A.foo`foo()
|
||||
}
|
||||
|
||||
~A.foo~fun A.foo() = 1
|
||||
|
||||
fun B.foo() = 2
|
||||
@@ -0,0 +1,7 @@
|
||||
class A
|
||||
class B {
|
||||
fun foo() = 1
|
||||
~A.foo~fun A.foo() = 2
|
||||
|
||||
fun A.bar() = `A.foo`foo()
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class A
|
||||
fun A.foo() = 2
|
||||
|
||||
class B {
|
||||
~foo~fun A.foo() = 1
|
||||
|
||||
fun A.bar() = `foo`foo()
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
class A {
|
||||
fun foo() = 1
|
||||
}
|
||||
class B {
|
||||
}
|
||||
~B.foo~fun B.foo() = 2
|
||||
|
||||
fun test(a: A, b: B) {
|
||||
with (a) {
|
||||
with (b) {
|
||||
`B.foo`foo()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R) : R = receiver.f()
|
||||
@@ -0,0 +1,12 @@
|
||||
class A {
|
||||
}
|
||||
~extension~fun A.foo() = 1
|
||||
fun foo() = 2
|
||||
|
||||
fun test(a: A) {
|
||||
with (a) {
|
||||
`extension`foo()
|
||||
}
|
||||
}
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R) : R = receiver.f()
|
||||
@@ -0,0 +1,8 @@
|
||||
class A {
|
||||
fun foo() = 1
|
||||
|
||||
fun test() {
|
||||
fun ~local~foo() = 2
|
||||
`local`foo()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class A {
|
||||
fun ~member~foo() = 1
|
||||
|
||||
fun test() {
|
||||
this.`member`foo()
|
||||
}
|
||||
}
|
||||
|
||||
fun A.foo() = 2
|
||||
@@ -0,0 +1,10 @@
|
||||
class A {
|
||||
fun ~member~foo() = 1
|
||||
|
||||
fun test() {
|
||||
this.`member`foo()
|
||||
}
|
||||
|
||||
fun A.foo() = 2
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
class A {
|
||||
fun ~member~foo() = 1
|
||||
}
|
||||
|
||||
fun A.foo() = 2
|
||||
|
||||
fun test(a: A) {
|
||||
with (a) {
|
||||
this.`member`foo()
|
||||
}
|
||||
}
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R) : R = receiver.f()
|
||||
@@ -0,0 +1,8 @@
|
||||
class A {
|
||||
fun ~member~foo() = 1
|
||||
|
||||
fun test() {
|
||||
fun A.foo() = 2
|
||||
this.`member`foo()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class A {
|
||||
~A.foo~fun foo() = 1
|
||||
}
|
||||
|
||||
class B {
|
||||
fun foo() = 2
|
||||
|
||||
fun A.bar() = `A.foo`foo()
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class A
|
||||
|
||||
class B {
|
||||
fun foo() = 2
|
||||
|
||||
fun A.bar() = `A.foo`foo()
|
||||
}
|
||||
|
||||
~A.foo~fun A.foo() = 1
|
||||
@@ -1105,11 +1105,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest("compiler/testData/codegen/box/classes/propertyInInitializer.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("resolveOrder.kt")
|
||||
public void testResolveOrder() throws Exception {
|
||||
doTest("compiler/testData/codegen/box/classes/resolveOrder.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("rightHandOverride.kt")
|
||||
public void testRightHandOverride() throws Exception {
|
||||
doTest("compiler/testData/codegen/box/classes/rightHandOverride.kt");
|
||||
|
||||
@@ -162,15 +162,80 @@ public class JetResolveTestGenerated extends AbstractResolveTest {
|
||||
public void testAllFilesPresentInCandidatesPriority() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/resolve/candidatesPriority"), Pattern.compile("^(.+)\\.resolve$"), true);
|
||||
}
|
||||
|
||||
|
||||
@TestMetadata("classObjectOuterResolve.resolve")
|
||||
public void testClassObjectOuterResolve() throws Exception {
|
||||
doTest("compiler/testData/resolve/candidatesPriority/classObjectOuterResolve.resolve");
|
||||
}
|
||||
|
||||
@TestMetadata("preferImplicitThisToNoReceiver.resolve")
|
||||
public void testPreferImplicitThisToNoReceiver() throws Exception {
|
||||
doTest("compiler/testData/resolve/candidatesPriority/preferImplicitThisToNoReceiver.resolve");
|
||||
@TestMetadata("closerReceiver1.resolve")
|
||||
public void testCloserReceiver1() throws Exception {
|
||||
doTest("compiler/testData/resolve/candidatesPriority/closerReceiver1.resolve");
|
||||
}
|
||||
|
||||
@TestMetadata("closerReceiver2.resolve")
|
||||
public void testCloserReceiver2() throws Exception {
|
||||
doTest("compiler/testData/resolve/candidatesPriority/closerReceiver2.resolve");
|
||||
}
|
||||
|
||||
@TestMetadata("closerReceiver3.resolve")
|
||||
public void testCloserReceiver3() throws Exception {
|
||||
doTest("compiler/testData/resolve/candidatesPriority/closerReceiver3.resolve");
|
||||
}
|
||||
|
||||
@TestMetadata("closerScope.resolve")
|
||||
public void testCloserScope() throws Exception {
|
||||
doTest("compiler/testData/resolve/candidatesPriority/closerScope.resolve");
|
||||
}
|
||||
|
||||
@TestMetadata("extensionToCloserReceiverVsMember.resolve")
|
||||
public void testExtensionToCloserReceiverVsMember() throws Exception {
|
||||
doTest("compiler/testData/resolve/candidatesPriority/extensionToCloserReceiverVsMember.resolve");
|
||||
}
|
||||
|
||||
@TestMetadata("implicitThisVsNoReceiver.resolve")
|
||||
public void testImplicitThisVsNoReceiver() throws Exception {
|
||||
doTest("compiler/testData/resolve/candidatesPriority/implicitThisVsNoReceiver.resolve");
|
||||
}
|
||||
|
||||
@TestMetadata("implicitThisVsNoReceiver2.resolve")
|
||||
public void testImplicitThisVsNoReceiver2() throws Exception {
|
||||
doTest("compiler/testData/resolve/candidatesPriority/implicitThisVsNoReceiver2.resolve");
|
||||
}
|
||||
|
||||
@TestMetadata("localVsImplicitThis.resolve")
|
||||
public void testLocalVsImplicitThis() throws Exception {
|
||||
doTest("compiler/testData/resolve/candidatesPriority/localVsImplicitThis.resolve");
|
||||
}
|
||||
|
||||
@TestMetadata("memberVsExtension1.resolve")
|
||||
public void testMemberVsExtension1() throws Exception {
|
||||
doTest("compiler/testData/resolve/candidatesPriority/memberVsExtension1.resolve");
|
||||
}
|
||||
|
||||
@TestMetadata("memberVsExtension2.resolve")
|
||||
public void testMemberVsExtension2() throws Exception {
|
||||
doTest("compiler/testData/resolve/candidatesPriority/memberVsExtension2.resolve");
|
||||
}
|
||||
|
||||
@TestMetadata("memberVsExtension3.resolve")
|
||||
public void testMemberVsExtension3() throws Exception {
|
||||
doTest("compiler/testData/resolve/candidatesPriority/memberVsExtension3.resolve");
|
||||
}
|
||||
|
||||
@TestMetadata("memberVsLocalExtension.resolve")
|
||||
public void testMemberVsLocalExtension() throws Exception {
|
||||
doTest("compiler/testData/resolve/candidatesPriority/memberVsLocalExtension.resolve");
|
||||
}
|
||||
|
||||
@TestMetadata("receiverVsThisObject.resolve")
|
||||
public void testReceiverVsThisObject() throws Exception {
|
||||
doTest("compiler/testData/resolve/candidatesPriority/receiverVsThisObject.resolve");
|
||||
}
|
||||
|
||||
@TestMetadata("receiverVsThisObject2.resolve")
|
||||
public void testReceiverVsThisObject2() throws Exception {
|
||||
doTest("compiler/testData/resolve/candidatesPriority/receiverVsThisObject2.resolve");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
fun box() : String {
|
||||
if (!B().test()) return "fail 1";
|
||||
if (!D().test()) return "fail 2"
|
||||
if (!F().test()) return "fail 3"
|
||||
if (!L().test()) return "fail 4"
|
||||
if (!H().test()) return "fail 5"
|
||||
if (!N().test()) return "fail 6"
|
||||
return "OK"
|
||||
}
|
||||
|
||||
class A {
|
||||
fun foo() = 1
|
||||
}
|
||||
|
||||
class B {
|
||||
fun foo() = 2
|
||||
|
||||
fun A.bar() = foo()
|
||||
|
||||
fun test() = A().bar() == 1
|
||||
}
|
||||
|
||||
|
||||
class C {
|
||||
fun D.foo() = 2
|
||||
}
|
||||
|
||||
class D {
|
||||
fun C.foo() = 1
|
||||
|
||||
fun C.bar() = foo()
|
||||
|
||||
fun test() = C().bar() == 1
|
||||
}
|
||||
|
||||
class E
|
||||
fun E.foo() = 2
|
||||
|
||||
class F {
|
||||
fun foo() = 1
|
||||
|
||||
fun E.bar() = foo()
|
||||
|
||||
fun test() = E().bar() == 1
|
||||
}
|
||||
|
||||
class G
|
||||
fun G.foo() = 2
|
||||
|
||||
class H {
|
||||
fun G.foo() = 1
|
||||
|
||||
fun G.bar() = foo()
|
||||
|
||||
fun test() = G().bar() == 1
|
||||
}
|
||||
|
||||
class K
|
||||
class L {
|
||||
fun K.bar() = foo()
|
||||
|
||||
fun test() = K().bar() == 1
|
||||
}
|
||||
fun K.foo() = 1
|
||||
fun L.foo() = 2
|
||||
|
||||
class M
|
||||
class N {
|
||||
fun foo() = 1
|
||||
fun M.foo() = 2
|
||||
|
||||
fun M.bar() = foo()
|
||||
|
||||
fun test() = M().bar() == 1
|
||||
}
|
||||
Reference in New Issue
Block a user