Support operator conventions for dynamic types

TODO:
- invoke
- += etc
This commit is contained in:
Andrey Breslav
2014-11-26 20:37:44 +03:00
parent fac53de40c
commit 300f484535
5 changed files with 189 additions and 53 deletions
@@ -20,6 +20,8 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import kotlin.Function0;
import kotlin.Function1;
import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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.storage.StorageManager;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.isOrOverridesSynthesized;
@@ -122,7 +124,8 @@ public class TaskPrioritizer {
) {
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) {
addCandidatesForInvoke(receiver, c);
return;
@@ -210,27 +213,36 @@ public class TaskPrioritizer {
TaskPrioritizerContext<D, F> onlyDynamicReceivers = c.replaceCollectors(TasksPackage.onlyDynamicReceivers(c.callableDescriptorCollectors));
addExtensionCandidates(explicitReceiver, implicitReceivers, onlyDynamicReceivers, isExplicit);
c.result.addCandidates(
new Function0<Collection<? extends ResolutionCandidate<D>>>() {
@Override
public Collection<? extends ResolutionCandidate<D>> invoke() {
//noinspection unchecked
D dynamicDescriptor = (D) DynamicCallableDescriptors.createCallableDescriptorForDynamicCall(
JetScope dynamicScope = DynamicCallableDescriptors.createDynamicDescriptorScope(
c.context.call,
c.scope.getContainingDeclaration()
);
if (dynamicDescriptor == null) return Collections.emptyList();
ResolutionCandidate<D> dynamicCandidate = ResolutionCandidate.create(
c.context.call,
dynamicDescriptor
Collection<D> dynamicDescriptors = new ArrayList<D>();
for (CallableDescriptorCollector<D> collector : c.callableDescriptorCollectors) {
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.BindingTrace
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 {
platformStatic fun createCallableDescriptorForDynamicCall(call: Call, owner: DeclarationDescriptor): CallableDescriptor? {
val callee = call.getCalleeExpression()
if (callee !is JetSimpleNameExpression) return null
val name = callee.getReferencedNameAsName()
platformStatic fun createDynamicDescriptorScope(call: Call, owner: DeclarationDescriptor) = object : JetScopeImpl() {
override fun getContainingDeclaration() = owner
return if (call.getValueArgumentList() == null && call.getValueArguments().isEmpty()) {
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?
)
override fun printScopeStructure(p: Printer) {
p.println(javaClass.getSimpleName(), ": dynamic candidates for " + call)
}
propertyDescriptor
override fun getFunctions(name: Name): Collection<FunctionDescriptor> {
return listOf(createDynamicFunction(owner, name, call))
}
else {
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
)
functionDescriptor
override fun getProperties(name: Name): Collection<VariableDescriptor> {
return if (call.getValueArgumentList() == null && call.getValueArguments().isEmpty()) {
listOf(createDynamicProperty(owner, name, call))
}
else listOf()
}
}
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 {
return ReceiverParameterDescriptorImpl(
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);
}
@TestMetadata("conventions.kt")
public void testConventions() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/conventions.kt");
doTest(fileName);
}
@TestMetadata("dynamicCalls.kt")
public void testDynamicCalls() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/dynamicCalls.kt");