Support operator conventions for dynamic types
TODO: - invoke - += etc
This commit is contained in:
+25
-13
@@ -20,6 +20,8 @@ import com.google.common.collect.Lists;
|
|||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
||||||
import kotlin.Function0;
|
import kotlin.Function0;
|
||||||
|
import kotlin.Function1;
|
||||||
|
import kotlin.KotlinPackage;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
@@ -43,8 +45,8 @@ import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
|||||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
|
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
|
||||||
import org.jetbrains.jet.storage.StorageManager;
|
import org.jetbrains.jet.storage.StorageManager;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.isOrOverridesSynthesized;
|
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.isOrOverridesSynthesized;
|
||||||
@@ -122,7 +124,8 @@ public class TaskPrioritizer {
|
|||||||
) {
|
) {
|
||||||
ProgressIndicatorProvider.checkCanceled();
|
ProgressIndicatorProvider.checkCanceled();
|
||||||
|
|
||||||
boolean resolveInvoke = c.context.call.getDispatchReceiver().exists();
|
ReceiverValue dispatchReceiver = c.context.call.getDispatchReceiver();
|
||||||
|
boolean resolveInvoke = dispatchReceiver.exists() && !TypesPackage.isDynamic(dispatchReceiver.getType());
|
||||||
if (resolveInvoke) {
|
if (resolveInvoke) {
|
||||||
addCandidatesForInvoke(receiver, c);
|
addCandidatesForInvoke(receiver, c);
|
||||||
return;
|
return;
|
||||||
@@ -210,27 +213,36 @@ public class TaskPrioritizer {
|
|||||||
TaskPrioritizerContext<D, F> onlyDynamicReceivers = c.replaceCollectors(TasksPackage.onlyDynamicReceivers(c.callableDescriptorCollectors));
|
TaskPrioritizerContext<D, F> onlyDynamicReceivers = c.replaceCollectors(TasksPackage.onlyDynamicReceivers(c.callableDescriptorCollectors));
|
||||||
addExtensionCandidates(explicitReceiver, implicitReceivers, onlyDynamicReceivers, isExplicit);
|
addExtensionCandidates(explicitReceiver, implicitReceivers, onlyDynamicReceivers, isExplicit);
|
||||||
|
|
||||||
|
|
||||||
c.result.addCandidates(
|
c.result.addCandidates(
|
||||||
new Function0<Collection<? extends ResolutionCandidate<D>>>() {
|
new Function0<Collection<? extends ResolutionCandidate<D>>>() {
|
||||||
@Override
|
@Override
|
||||||
public Collection<? extends ResolutionCandidate<D>> invoke() {
|
public Collection<? extends ResolutionCandidate<D>> invoke() {
|
||||||
|
|
||||||
//noinspection unchecked
|
JetScope dynamicScope = DynamicCallableDescriptors.createDynamicDescriptorScope(
|
||||||
D dynamicDescriptor = (D) DynamicCallableDescriptors.createCallableDescriptorForDynamicCall(
|
|
||||||
c.context.call,
|
c.context.call,
|
||||||
c.scope.getContainingDeclaration()
|
c.scope.getContainingDeclaration()
|
||||||
);
|
);
|
||||||
if (dynamicDescriptor == null) return Collections.emptyList();
|
|
||||||
|
|
||||||
ResolutionCandidate<D> dynamicCandidate = ResolutionCandidate.create(
|
Collection<D> dynamicDescriptors = new ArrayList<D>();
|
||||||
c.context.call,
|
for (CallableDescriptorCollector<D> collector : c.callableDescriptorCollectors) {
|
||||||
dynamicDescriptor
|
dynamicDescriptors.addAll(collector.getNonExtensionsByName(dynamicScope, c.name, c.context.trace));
|
||||||
|
}
|
||||||
|
|
||||||
|
return KotlinPackage.map(
|
||||||
|
dynamicDescriptors,
|
||||||
|
new Function1<D, ResolutionCandidate<D>>() {
|
||||||
|
@Override
|
||||||
|
public ResolutionCandidate<D> invoke(D dynamicDescriptor) {
|
||||||
|
ResolutionCandidate<D> dynamicCandidate = ResolutionCandidate.create(
|
||||||
|
c.context.call,
|
||||||
|
dynamicDescriptor
|
||||||
|
);
|
||||||
|
dynamicCandidate.setDispatchReceiver(explicitReceiver);
|
||||||
|
dynamicCandidate.setExplicitReceiverKind(DISPATCH_RECEIVER);
|
||||||
|
return dynamicCandidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
dynamicCandidate.setDispatchReceiver(explicitReceiver);
|
|
||||||
dynamicCandidate.setExplicitReceiverKind(DISPATCH_RECEIVER);
|
|
||||||
|
|
||||||
return Collections.singletonList(dynamicCandidate);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -43,55 +43,77 @@ import org.jetbrains.jet.lang.resolve.calls.tasks.collectors.CallableDescriptorC
|
|||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace
|
import org.jetbrains.jet.lang.resolve.BindingTrace
|
||||||
import org.jetbrains.jet.lang.resolve.calls.tasks.collectors.CallableDescriptorCollectors
|
import org.jetbrains.jet.lang.resolve.calls.tasks.collectors.CallableDescriptorCollectors
|
||||||
|
import org.jetbrains.jet.lexer.JetToken
|
||||||
|
import org.jetbrains.jet.lang.psi.JetOperationReferenceExpression
|
||||||
|
import org.jetbrains.jet.lang.psi.JetArrayAccessExpression
|
||||||
|
import java.util.ArrayList
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl
|
||||||
|
import org.jetbrains.jet.utils.Printer
|
||||||
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.jet.lang.descriptors.VariableDescriptor
|
||||||
|
|
||||||
object DynamicCallableDescriptors {
|
object DynamicCallableDescriptors {
|
||||||
|
|
||||||
platformStatic fun createCallableDescriptorForDynamicCall(call: Call, owner: DeclarationDescriptor): CallableDescriptor? {
|
platformStatic fun createDynamicDescriptorScope(call: Call, owner: DeclarationDescriptor) = object : JetScopeImpl() {
|
||||||
val callee = call.getCalleeExpression()
|
override fun getContainingDeclaration() = owner
|
||||||
if (callee !is JetSimpleNameExpression) return null
|
|
||||||
val name = callee.getReferencedNameAsName()
|
|
||||||
|
|
||||||
return if (call.getValueArgumentList() == null && call.getValueArguments().isEmpty()) {
|
override fun printScopeStructure(p: Printer) {
|
||||||
val propertyDescriptor = PropertyDescriptorImpl.create(
|
p.println(javaClass.getSimpleName(), ": dynamic candidates for " + call)
|
||||||
owner,
|
}
|
||||||
Annotations.EMPTY,
|
|
||||||
Modality.FINAL,
|
|
||||||
Visibilities.PUBLIC,
|
|
||||||
true,
|
|
||||||
name,
|
|
||||||
CallableMemberDescriptor.Kind.DECLARATION,
|
|
||||||
SourceElement.NO_SOURCE
|
|
||||||
)
|
|
||||||
propertyDescriptor.setType(
|
|
||||||
DynamicType,
|
|
||||||
createTypeParameters(propertyDescriptor, call),
|
|
||||||
createDynamicDispatchReceiverParameter(propertyDescriptor),
|
|
||||||
null: JetType?
|
|
||||||
)
|
|
||||||
|
|
||||||
propertyDescriptor
|
override fun getFunctions(name: Name): Collection<FunctionDescriptor> {
|
||||||
|
return listOf(createDynamicFunction(owner, name, call))
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
val functionDescriptor = SimpleFunctionDescriptorImpl.create(
|
override fun getProperties(name: Name): Collection<VariableDescriptor> {
|
||||||
owner,
|
return if (call.getValueArgumentList() == null && call.getValueArguments().isEmpty()) {
|
||||||
Annotations.EMPTY,
|
listOf(createDynamicProperty(owner, name, call))
|
||||||
name,
|
}
|
||||||
CallableMemberDescriptor.Kind.DECLARATION,
|
else listOf()
|
||||||
SourceElement.NO_SOURCE
|
|
||||||
)
|
|
||||||
functionDescriptor.initialize(
|
|
||||||
null,
|
|
||||||
createDynamicDispatchReceiverParameter(functionDescriptor),
|
|
||||||
createTypeParameters(functionDescriptor, call),
|
|
||||||
createValueParameters(functionDescriptor, call),
|
|
||||||
DynamicType,
|
|
||||||
Modality.FINAL,
|
|
||||||
Visibilities.PUBLIC
|
|
||||||
)
|
|
||||||
functionDescriptor
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createDynamicProperty(owner: DeclarationDescriptor, name: Name, call: Call): PropertyDescriptorImpl {
|
||||||
|
val propertyDescriptor = PropertyDescriptorImpl.create(
|
||||||
|
owner,
|
||||||
|
Annotations.EMPTY,
|
||||||
|
Modality.FINAL,
|
||||||
|
Visibilities.PUBLIC,
|
||||||
|
true,
|
||||||
|
name,
|
||||||
|
CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
|
SourceElement.NO_SOURCE
|
||||||
|
)
|
||||||
|
propertyDescriptor.setType(
|
||||||
|
DynamicType,
|
||||||
|
createTypeParameters(propertyDescriptor, call),
|
||||||
|
createDynamicDispatchReceiverParameter(propertyDescriptor),
|
||||||
|
null: JetType?
|
||||||
|
)
|
||||||
|
|
||||||
|
return propertyDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createDynamicFunction(owner: DeclarationDescriptor, name: Name, call: Call): SimpleFunctionDescriptorImpl {
|
||||||
|
val functionDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||||
|
owner,
|
||||||
|
Annotations.EMPTY,
|
||||||
|
name,
|
||||||
|
CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
|
SourceElement.NO_SOURCE
|
||||||
|
)
|
||||||
|
functionDescriptor.initialize(
|
||||||
|
null,
|
||||||
|
createDynamicDispatchReceiverParameter(functionDescriptor),
|
||||||
|
createTypeParameters(functionDescriptor, call),
|
||||||
|
createValueParameters(functionDescriptor, call),
|
||||||
|
DynamicType,
|
||||||
|
Modality.FINAL,
|
||||||
|
Visibilities.PUBLIC
|
||||||
|
)
|
||||||
|
return functionDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
private fun createDynamicDispatchReceiverParameter(owner: CallableDescriptor): ReceiverParameterDescriptorImpl {
|
private fun createDynamicDispatchReceiverParameter(owner: CallableDescriptor): ReceiverParameterDescriptorImpl {
|
||||||
return ReceiverParameterDescriptorImpl(
|
return ReceiverParameterDescriptorImpl(
|
||||||
owner,
|
owner,
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
// !MARK_DYNAMIC_CALLS
|
||||||
|
|
||||||
|
// MODULE[js]: m1
|
||||||
|
// FILE: k.kt
|
||||||
|
|
||||||
|
fun test(d: dynamic) {
|
||||||
|
<!DEBUG_INFO_DYNAMIC!>+<!>d
|
||||||
|
<!DEBUG_INFO_DYNAMIC!>-<!>d
|
||||||
|
<!DEBUG_INFO_DYNAMIC!>!<!> d
|
||||||
|
|
||||||
|
|
||||||
|
d <!DEBUG_INFO_DYNAMIC!>+<!> d
|
||||||
|
d <!DEBUG_INFO_DYNAMIC!>+<!> 1
|
||||||
|
"" + d
|
||||||
|
|
||||||
|
d <!DEBUG_INFO_DYNAMIC!>-<!> d
|
||||||
|
d <!DEBUG_INFO_DYNAMIC!>*<!> d
|
||||||
|
d <!DEBUG_INFO_DYNAMIC!>/<!> d
|
||||||
|
d <!DEBUG_INFO_DYNAMIC!>%<!> d
|
||||||
|
|
||||||
|
d<!DEBUG_INFO_DYNAMIC!>..<!>d
|
||||||
|
|
||||||
|
d <!DEBUG_INFO_DYNAMIC!>and<!> d
|
||||||
|
|
||||||
|
d <!DEBUG_INFO_DYNAMIC!>in<!> d
|
||||||
|
d <!DEBUG_INFO_DYNAMIC!>!in<!> d
|
||||||
|
|
||||||
|
1 <!DEBUG_INFO_DYNAMIC!>in<!> d
|
||||||
|
1 <!DEBUG_INFO_DYNAMIC!>!in<!> d
|
||||||
|
|
||||||
|
<!DEBUG_INFO_DYNAMIC!>d[1]<!>
|
||||||
|
<!DEBUG_INFO_DYNAMIC!>d[1, 2]<!>
|
||||||
|
|
||||||
|
<!DEBUG_INFO_DYNAMIC!>d[1]<!> = 2
|
||||||
|
<!DEBUG_INFO_DYNAMIC!>d[1, 2]<!> = 3
|
||||||
|
|
||||||
|
<!DEBUG_INFO_DYNAMIC!>d[1]<!><!DEBUG_INFO_DYNAMIC!>++<!>
|
||||||
|
<!DEBUG_INFO_DYNAMIC!>++<!><!DEBUG_INFO_DYNAMIC!>d[1]<!>
|
||||||
|
|
||||||
|
<!DEBUG_INFO_DYNAMIC!>d[1]<!><!DEBUG_INFO_DYNAMIC!>--<!>
|
||||||
|
<!DEBUG_INFO_DYNAMIC!>--<!><!DEBUG_INFO_DYNAMIC!>d[1]<!>
|
||||||
|
|
||||||
|
// d()
|
||||||
|
// d(1)
|
||||||
|
// d(name = 1)
|
||||||
|
// d {}
|
||||||
|
|
||||||
|
d == d
|
||||||
|
d != d
|
||||||
|
|
||||||
|
d === d
|
||||||
|
d !== d
|
||||||
|
|
||||||
|
d <!DEBUG_INFO_DYNAMIC!><<!> d
|
||||||
|
d <!DEBUG_INFO_DYNAMIC!><=<!> d
|
||||||
|
d <!DEBUG_INFO_DYNAMIC!>>=<!> d
|
||||||
|
d <!DEBUG_INFO_DYNAMIC!>><!> d
|
||||||
|
|
||||||
|
for (i in <!DEBUG_INFO_DYNAMIC!>d<!>) {
|
||||||
|
i.<!DEBUG_INFO_DYNAMIC!>foo<!>()
|
||||||
|
}
|
||||||
|
|
||||||
|
val (<!DEBUG_INFO_DYNAMIC!>a<!>, <!DEBUG_INFO_DYNAMIC!>b<!>, <!DEBUG_INFO_DYNAMIC!>c<!>) = d
|
||||||
|
a.<!DEBUG_INFO_DYNAMIC!>foo<!>()
|
||||||
|
b.<!DEBUG_INFO_DYNAMIC!>foo<!>()
|
||||||
|
c.<!DEBUG_INFO_DYNAMIC!>foo<!>()
|
||||||
|
|
||||||
|
var dVar = d
|
||||||
|
dVar<!DEBUG_INFO_DYNAMIC!>++<!>
|
||||||
|
<!DEBUG_INFO_DYNAMIC!>++<!>dVar
|
||||||
|
|
||||||
|
dVar<!DEBUG_INFO_DYNAMIC!>--<!>
|
||||||
|
<!DEBUG_INFO_DYNAMIC!>--<!>dVar
|
||||||
|
|
||||||
|
// dVar += 1
|
||||||
|
// dVar -= 1
|
||||||
|
// dVar *= 1
|
||||||
|
// dVar /= 1
|
||||||
|
// dVar %= 1
|
||||||
|
|
||||||
|
// d[1] += 1
|
||||||
|
// d[1] -= 1
|
||||||
|
// d[1] *= 1
|
||||||
|
// d[1] /= 1
|
||||||
|
// d[1] %= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
val dyn: dynamic = null
|
||||||
|
val foo : Int <!DEBUG_INFO_DYNAMIC!>by dyn<!>
|
||||||
|
var bar : Int <!DEBUG_INFO_DYNAMIC!>by dyn<!>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
internal var bar: kotlin.Int
|
||||||
|
internal val dyn: dynamic = null
|
||||||
|
internal val foo: kotlin.Int
|
||||||
|
internal fun test(/*0*/ d: dynamic): kotlin.Unit
|
||||||
@@ -3740,6 +3740,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("conventions.kt")
|
||||||
|
public void testConventions() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/conventions.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("dynamicCalls.kt")
|
@TestMetadata("dynamicCalls.kt")
|
||||||
public void testDynamicCalls() throws Exception {
|
public void testDynamicCalls() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/dynamicCalls.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/dynamicCalls.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user