From c58d4fd6d2dd529778dcab8445c3faa392f13b95 Mon Sep 17 00:00:00 2001 From: "Natalia.Ukhorskaya" Date: Tue, 30 Apr 2013 15:35:25 +0400 Subject: [PATCH] Resolve expression in property delegate --- .../jet/lang/resolve/BindingContext.java | 3 + .../jet/lang/resolve/BodyResolver.java | 90 +++++----- .../jet/lang/resolve/DescriptorResolver.java | 36 +++- .../lang/resolve/scopes/JetScopeUtils.java | 22 +++ .../expressions/DelegatedPropertyUtils.java | 164 ++++++++++++++++++ .../delegatedPropertyOverridedInTrait.kt | 18 ++ .../delegatedProperty/propertyDefferedType.kt | 10 ++ .../tests/delegatedProperty/recursiveType.kt | 13 ++ .../tests/delegatedProperty/thisInDelegate.kt | 12 ++ .../delegationByCall.resolve | 6 + .../delegationByConstructor.resolve | 4 + .../delegatedProperty/delegationByFun.resolve | 5 + .../delegationByObject.resolve | 4 + .../delegationByProperty.resolve | 6 + .../delegationInClass.resolve | 9 + .../delegatedProperty/localDelegation.resolve | 11 ++ .../checkers/JetDiagnosticsTestGenerated.java | 20 +++ 17 files changed, 391 insertions(+), 42 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DelegatedPropertyUtils.java create mode 100644 compiler/testData/diagnostics/tests/delegatedProperty/delegatedPropertyOverridedInTrait.kt create mode 100644 compiler/testData/diagnostics/tests/delegatedProperty/propertyDefferedType.kt create mode 100644 compiler/testData/diagnostics/tests/delegatedProperty/recursiveType.kt create mode 100644 compiler/testData/diagnostics/tests/delegatedProperty/thisInDelegate.kt create mode 100644 compiler/testData/resolve/delegatedProperty/delegationByCall.resolve create mode 100644 compiler/testData/resolve/delegatedProperty/delegationByConstructor.resolve create mode 100644 compiler/testData/resolve/delegatedProperty/delegationByFun.resolve create mode 100644 compiler/testData/resolve/delegatedProperty/delegationByObject.resolve create mode 100644 compiler/testData/resolve/delegatedProperty/delegationByProperty.resolve create mode 100644 compiler/testData/resolve/delegatedProperty/delegationInClass.resolve create mode 100644 compiler/testData/resolve/delegatedProperty/localDelegation.resolve diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java index 8559d57d4ed..fe4b97949a4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -95,6 +95,9 @@ public interface BindingContext { WritableSlice> LOOP_RANGE_HAS_NEXT_RESOLVED_CALL = Slices.createSimpleSlice(); WritableSlice> LOOP_RANGE_NEXT_RESOLVED_CALL = Slices.createSimpleSlice(); + WritableSlice> DELEGATED_PROPERTY_RESOLVED_CALL = Slices.createSimpleSlice(); + WritableSlice DELEGATED_PROPERTY_CALL = Slices.createSimpleSlice(); + WritableSlice> COMPONENT_RESOLVED_CALL = Slices.createSimpleSlice(); WritableSlice> INDEXED_LVALUE_GET = Slices.createSimpleSlice(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index 66930366d06..c2f382593bd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -30,13 +30,11 @@ import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; -import org.jetbrains.jet.lang.resolve.scopes.JetScope; -import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler; -import org.jetbrains.jet.lang.resolve.scopes.WritableScope; -import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; +import org.jetbrains.jet.lang.resolve.scopes.*; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; +import org.jetbrains.jet.lang.types.expressions.DelegatedPropertyUtils; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.util.Box; @@ -123,7 +121,6 @@ public class BodyResolver { resolveDelegationSpecifierLists(); resolveClassAnnotations(); - resolvePropertyDelegates(); resolvePropertyDeclarationBodies(); resolveAnonymousInitializers(); resolvePrimaryConstructorParameters(); @@ -153,27 +150,6 @@ public class BodyResolver { } } - private void resolvePropertyDelegates() { - for (Map.Entry entry : context.getProperties().entrySet()) { - JetProperty jetProperty = entry.getKey(); - - JetExpression delegateExpression = jetProperty.getDelegateExpression(); - if (delegateExpression == null) continue; - - JetPropertyAccessor getter = jetProperty.getGetter(); - if (getter != null) { - trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(getter)); - } - - JetPropertyAccessor setter = jetProperty.getSetter(); - if (setter != null) { - trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(setter)); - } - - //todo resolve delegate expression - } - } - private void resolveDelegationSpecifierList(JetClassOrObject jetClass, MutableClassDescriptor descriptor) { resolveDelegationSpecifierList(jetClass, descriptor, descriptor.getUnsubstitutedPrimaryConstructor(), @@ -413,6 +389,12 @@ public class BodyResolver { } } + JetExpression delegateExpression = property.getDelegateExpression(); + if (delegateExpression != null) { + assert initializer == null : "Initializer should be null for delegated property : " + property.getText(); + resolvePropertyDelegate(property, propertyDescriptor, delegateExpression, classDescriptor.getScopeForMemberResolution()); + } + resolvePropertyAccessors(property, propertyDescriptor); processed.add(property); } @@ -433,21 +415,21 @@ public class BodyResolver { resolvePropertyInitializer(property, propertyDescriptor, initializer); } + JetExpression delegateExpression = property.getDelegateExpression(); + if (delegateExpression != null) { + assert initializer == null : "Initializer should be null for delegated property : " + property.getText(); + JetScope scope = context.getDeclaringScopes().apply(property); + resolvePropertyDelegate(property, propertyDescriptor, delegateExpression, scope); + } + resolvePropertyAccessors(property, propertyDescriptor); } } - private JetScope makeScopeForPropertyAccessor(@NotNull JetPropertyAccessor accessor, PropertyDescriptor propertyDescriptor) { - JetScope declaringScope = context.getDeclaringScopes().apply(accessor); - - JetScope propertyDeclarationInnerScope = descriptorResolver.getPropertyDeclarationInnerScope( - propertyDescriptor, declaringScope, propertyDescriptor.getTypeParameters(), propertyDescriptor.getReceiverParameter(), - trace); - WritableScope accessorScope = new WritableScopeImpl( - propertyDeclarationInnerScope, declaringScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(trace), "Accessor scope"); - accessorScope.changeLockLevel(WritableScope.LockLevel.READING); - - return accessorScope; + private JetScope makeScopeForPropertyAccessor(@NotNull JetPropertyAccessor accessor, @NotNull PropertyDescriptor descriptor) { + JetScope accessorDeclaringScope = context.getDeclaringScopes().apply(accessor); + assert accessorDeclaringScope != null : "Scope for accessor " + accessor.getText() + " should exists"; + return JetScopeUtils.makeScopeForPropertyAccessor(descriptor, accessorDeclaringScope, descriptorResolver, trace); } public void resolvePropertyAccessors(JetProperty property, PropertyDescriptor propertyDescriptor) { @@ -485,8 +467,38 @@ public class BodyResolver { }); } + private void resolvePropertyDelegate( + @NotNull JetProperty jetProperty, + @NotNull PropertyDescriptor propertyDescriptor, + @NotNull JetExpression delegateExpression, + @NotNull JetScope parentScopeForAccessor + ) { + JetPropertyAccessor getter = jetProperty.getGetter(); + if (getter != null) { + trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(getter)); + } + + JetPropertyAccessor setter = jetProperty.getSetter(); + if (setter != null) { + trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(setter)); + } + + JetScope scope = makeScopeForPropertyInitializerOrDelegate(jetProperty, propertyDescriptor); + JetType delegateType = expressionTypingServices.safeGetType(scope, delegateExpression, NO_EXPECTED_TYPE, + DataFlowInfo.EMPTY, trace); + + JetScope accessorScope = JetScopeUtils.makeScopeForPropertyAccessor(propertyDescriptor, parentScopeForAccessor, descriptorResolver, trace); + DelegatedPropertyUtils.resolveDelegatedPropertyGetMethod(propertyDescriptor, delegateExpression, delegateType, + expressionTypingServices, trace, accessorScope); + + if (jetProperty.isVar()) { + DelegatedPropertyUtils.resolveDelegatedPropertySetMethod(propertyDescriptor, delegateExpression, delegateType, + expressionTypingServices, trace, accessorScope); + } + } + private void resolvePropertyInitializer(JetProperty property, PropertyDescriptor propertyDescriptor, JetExpression initializer) { - JetScope propertyDeclarationInnerScope = makeScopeForPropertyInitializer(property, propertyDescriptor); + JetScope propertyDeclarationInnerScope = makeScopeForPropertyInitializerOrDelegate(property, propertyDescriptor); resolvePropertyInitializer(property, propertyDescriptor, initializer, propertyDeclarationInnerScope); } @@ -498,7 +510,7 @@ public class BodyResolver { } @NotNull - private JetScope makeScopeForPropertyInitializer(@NotNull JetProperty property, @NotNull PropertyDescriptor descriptor) { + private JetScope makeScopeForPropertyInitializerOrDelegate(@NotNull JetProperty property, @NotNull PropertyDescriptor descriptor) { JetScope scope = this.context.getDeclaringScopes().apply(property); assert scope != null : "Scope for property " + property.getText() + " should exists"; return descriptorResolver.getPropertyDeclarationInnerScopeForInitializer( diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java index 71fb77afc7a..ff231209d09 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.JetScopeUtils; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; @@ -38,6 +39,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; +import org.jetbrains.jet.lang.types.expressions.DelegatedPropertyUtils; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lexer.JetKeywordToken; @@ -993,9 +995,17 @@ public class DescriptorResolver { if (propertyTypeRef == null) { final JetExpression initializer = variable.getInitializer(); if (initializer == null) { - if (hasDelegate) { - // todo resolve type from delegate - return ErrorUtils.createErrorType("Type from delegate"); + if (hasDelegate && variableDescriptor instanceof PropertyDescriptor) { + final JetExpression propertyDelegateExpression = ((JetProperty) variable).getDelegateExpression(); + if (propertyDelegateExpression != null) { + return DeferredType.create(trace, new RecursionIntolerantLazyValueWithDefault(ErrorUtils.createErrorType("Recursive dependency")) { + @Override + protected JetType compute() { + return resolveDelegatedPropertyType((PropertyDescriptor) variableDescriptor, scope, + propertyDelegateExpression, dataFlowInfo, trace); + } + }); + } } if (!notLocal) { trace.report(VARIABLE_WITH_NO_TYPE_NO_INITIALIZER.on(variable)); @@ -1023,6 +1033,26 @@ public class DescriptorResolver { } } + @NotNull + private JetType resolveDelegatedPropertyType( + @NotNull PropertyDescriptor propertyDescriptor, + @NotNull JetScope scope, + @NotNull JetExpression delegateExpression, + @NotNull DataFlowInfo dataFlowInfo, + @NotNull BindingTrace trace + ) { + JetType type = expressionTypingServices.safeGetType(scope, delegateExpression, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo, trace); + + JetScope accessorScope = JetScopeUtils.makeScopeForPropertyAccessor(propertyDescriptor, scope, this, trace); + JetType getterReturnType = DelegatedPropertyUtils + .getDelegatedPropertyGetMethodReturnType(propertyDescriptor, delegateExpression, type, expressionTypingServices, trace, + accessorScope); + if (getterReturnType != null) { + return getterReturnType; + } + return ErrorUtils.createErrorType("Type from delegate"); + } + @Nullable private JetType transformAnonymousTypeIfNeeded( @NotNull DeclarationDescriptorWithVisibility descriptor, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeUtils.java index 56edb67ee93..ae6b98334bb 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeUtils.java @@ -23,7 +23,11 @@ import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.DescriptorResolver; +import org.jetbrains.jet.lang.resolve.TraceBasedRedeclarationHandler; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import java.util.Collection; @@ -67,4 +71,22 @@ public final class JetScopeUtils { return result; } + + public static JetScope makeScopeForPropertyAccessor( + @NotNull PropertyDescriptor propertyDescriptor, + @NotNull JetScope parentScope, + @NotNull DescriptorResolver descriptorResolver, + @NotNull BindingTrace trace + ) { + JetScope propertyDeclarationInnerScope = descriptorResolver + .getPropertyDeclarationInnerScope(propertyDescriptor, parentScope, + propertyDescriptor.getTypeParameters(), + propertyDescriptor.getReceiverParameter(), trace); + WritableScope accessorScope = new WritableScopeImpl(propertyDeclarationInnerScope, parentScope.getContainingDeclaration(), + new TraceBasedRedeclarationHandler(trace), "Accessor Scope"); + accessorScope.changeLockLevel(WritableScope.LockLevel.READING); + + return accessorScope; + } + } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DelegatedPropertyUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DelegatedPropertyUtils.java new file mode 100644 index 00000000000..bd06475ea1e --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DelegatedPropertyUtils.java @@ -0,0 +1,164 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.types.expressions; + +import com.google.common.collect.Lists; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +import org.jetbrains.jet.lang.psi.Call; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetReferenceExpression; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; +import org.jetbrains.jet.lang.resolve.calls.context.ExpressionPosition; +import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; +import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults; +import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; +import org.jetbrains.jet.lang.types.DeferredType; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeUtils; +import org.jetbrains.jet.lang.types.checker.JetTypeChecker; + +import java.util.List; + +import static org.jetbrains.jet.lang.psi.JetPsiFactory.createExpression; +import static org.jetbrains.jet.lang.psi.JetPsiFactory.createSimpleName; +import static org.jetbrains.jet.lang.resolve.BindingContext.*; +import static org.jetbrains.jet.lang.resolve.BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL; +import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; +import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.createFakeExpressionOfType; + +public class DelegatedPropertyUtils { + + @Nullable + public static JetType getDelegatedPropertyGetMethodReturnType( + @NotNull PropertyDescriptor propertyDescriptor, + @NotNull JetExpression delegateExpression, + @NotNull JetType delegateType, + @NotNull ExpressionTypingServices expressionTypingServices, + @NotNull BindingTrace trace, + @NotNull JetScope scope + ) { + resolveDelegatedPropertyConventionMethod(propertyDescriptor, delegateExpression, delegateType, expressionTypingServices, trace, + scope, true); + return getDelegateGetMethodReturnType(trace.getBindingContext(), propertyDescriptor); + } + + @Nullable + private static JetType getDelegateGetMethodReturnType(@NotNull BindingContext context, @NotNull PropertyDescriptor descriptor) { + ResolvedCall resolvedCall = + context.get(DELEGATED_PROPERTY_RESOLVED_CALL, descriptor.getGetter()); + return resolvedCall != null ? resolvedCall.getResultingDescriptor().getReturnType() : null; + } + + public static void resolveDelegatedPropertyGetMethod( + @NotNull PropertyDescriptor propertyDescriptor, + @NotNull JetExpression delegateExpression, + @NotNull JetType delegateType, + @NotNull ExpressionTypingServices expressionTypingServices, + @NotNull BindingTrace trace, + @NotNull JetScope scope + ) { + resolveDelegatedPropertyConventionMethod(propertyDescriptor, delegateExpression, delegateType, expressionTypingServices, trace, + scope, true); + JetType returnType = getDelegateGetMethodReturnType(trace.getBindingContext(), propertyDescriptor); + JetType propertyType = propertyDescriptor.getType(); + if (propertyType instanceof DeferredType) { + assert ((DeferredType) propertyType).isComputed() : "Property type should be computed when resolving delegate convention method"; + } + + if (returnType != null && !JetTypeChecker.INSTANCE.isSubtypeOf(returnType, propertyType)) { + //todo report error + } + } + + public static void resolveDelegatedPropertySetMethod( + @NotNull PropertyDescriptor propertyDescriptor, + @NotNull JetExpression delegateExpression, + @NotNull JetType delegateType, + @NotNull ExpressionTypingServices expressionTypingServices, + @NotNull BindingTrace trace, + @NotNull JetScope scope + ) { + resolveDelegatedPropertyConventionMethod(propertyDescriptor, delegateExpression, delegateType, expressionTypingServices, trace, + scope, false); + } + + /* Resolve get() or set() methods from delegate */ + private static void resolveDelegatedPropertyConventionMethod( + @NotNull PropertyDescriptor propertyDescriptor, + @NotNull JetExpression delegateExpression, + @NotNull JetType delegateType, + @NotNull ExpressionTypingServices expressionTypingServices, + @NotNull BindingTrace trace, + @NotNull JetScope scope, + boolean isGet + ) { + PropertyAccessorDescriptor accessor = isGet ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter(); + assert accessor != null : "Delegated property should have getter/setter " + propertyDescriptor + " " + delegateExpression.getText(); + + Call call = trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, accessor); + if (call != null) return; + + ExpressionTypingContext context = ExpressionTypingContext.newContext( + expressionTypingServices, trace, scope, + DataFlowInfo.EMPTY, TypeUtils.NO_EXPECTED_TYPE, ExpressionPosition.FREE); + Project project = context.expressionTypingServices.getProject(); + + boolean hasThis = propertyDescriptor.getReceiverParameter() != null || propertyDescriptor.getExpectedThisObject() != null; + + List arguments = Lists.newArrayList(); + arguments.add(createExpression(project, hasThis ? "this" : "null")); + arguments.add(createExpression(project, "\"" + propertyDescriptor.getName().getName() + "\"")); + if (!isGet) { + JetReferenceExpression fakeArgument = createFakeExpressionOfType(context.expressionTypingServices.getProject(), trace, + "fakeArgument" + arguments.size(), + propertyDescriptor.getType()); + arguments.add(fakeArgument); + List valueParameters = accessor.getValueParameters(); + context.trace.record(REFERENCE_TARGET, fakeArgument, valueParameters.get(0)); + } + + Name functionName = Name.identifier(isGet ? "get" : "set"); + JetReferenceExpression fakeCalleeExpression = createSimpleName(project, functionName.getName()); + + ExpressionReceiver receiver = new ExpressionReceiver(delegateExpression, delegateType); + call = CallMaker.makeCallWithExpressions(fakeCalleeExpression, receiver, null, fakeCalleeExpression, arguments, Call.CallType.DEFAULT); + context.trace.record(BindingContext.DELEGATED_PROPERTY_CALL, accessor, call); + + OverloadResolutionResults functionResults = context.resolveCallWithGivenName(call, fakeCalleeExpression, functionName); + + if (!functionResults.isSuccess()) { + //todo report errors + return; + } + + context.trace.record(DELEGATED_PROPERTY_RESOLVED_CALL, accessor, functionResults.getResultingCall()); + } + + private DelegatedPropertyUtils() { + } +} diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/delegatedPropertyOverridedInTrait.kt b/compiler/testData/diagnostics/tests/delegatedProperty/delegatedPropertyOverridedInTrait.kt new file mode 100644 index 00000000000..c083c4a26ee --- /dev/null +++ b/compiler/testData/diagnostics/tests/delegatedProperty/delegatedPropertyOverridedInTrait.kt @@ -0,0 +1,18 @@ +trait A { + val prop: Int +} + +class AImpl: A { + override val prop by Delegate() +} + +fun foo() { + AImpl().prop +} + +class Delegate { + fun get(t: Any?, p: String): Int { + t.equals(p) // to avoid UNUSED_PARAMETER warning + return 1 + } +} diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/propertyDefferedType.kt b/compiler/testData/diagnostics/tests/delegatedProperty/propertyDefferedType.kt new file mode 100644 index 00000000000..0cac6de9ae3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/delegatedProperty/propertyDefferedType.kt @@ -0,0 +1,10 @@ +class B { + val c by Delegate(ag) +} + +class Delegate(val init: T) { + fun get(t: Any?, p: String): Int { + t.equals(p) // to avoid UNUSED_PARAMETER warning + throw Exception() + } +} diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/recursiveType.kt b/compiler/testData/diagnostics/tests/delegatedProperty/recursiveType.kt new file mode 100644 index 00000000000..94643d045ee --- /dev/null +++ b/compiler/testData/diagnostics/tests/delegatedProperty/recursiveType.kt @@ -0,0 +1,13 @@ +val a by a + +val b by Delegate(b) + +val c by d +val d by c + +class Delegate(i: Int) { + fun get(t: Any?, p: String): Int { + t.equals(p) // to avoid UNUSED_PARAMETER warning + return 1 + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/thisInDelegate.kt b/compiler/testData/diagnostics/tests/delegatedProperty/thisInDelegate.kt new file mode 100644 index 00000000000..c8744d12581 --- /dev/null +++ b/compiler/testData/diagnostics/tests/delegatedProperty/thisInDelegate.kt @@ -0,0 +1,12 @@ +val Int.a by Delegate(this) + +class A { + val Int.a by Delegate(this) +} + +class Delegate(i: Int) { + fun get(t: Any?, p: String): Int { + t.equals(p) // to avoid UNUSED_PARAMETER warning + return 1 + } +} \ No newline at end of file diff --git a/compiler/testData/resolve/delegatedProperty/delegationByCall.resolve b/compiler/testData/resolve/delegatedProperty/delegationByCall.resolve new file mode 100644 index 00000000000..b4509beae60 --- /dev/null +++ b/compiler/testData/resolve/delegatedProperty/delegationByCall.resolve @@ -0,0 +1,6 @@ +~A~class A { + ~foo~fun foo() = A() +} + +val a: Int by `A`A().`foo`foo() + diff --git a/compiler/testData/resolve/delegatedProperty/delegationByConstructor.resolve b/compiler/testData/resolve/delegatedProperty/delegationByConstructor.resolve new file mode 100644 index 00000000000..c1deb75d709 --- /dev/null +++ b/compiler/testData/resolve/delegatedProperty/delegationByConstructor.resolve @@ -0,0 +1,4 @@ +~A~class A + +val a: Int by `A`A() + diff --git a/compiler/testData/resolve/delegatedProperty/delegationByFun.resolve b/compiler/testData/resolve/delegatedProperty/delegationByFun.resolve new file mode 100644 index 00000000000..eba9a102672 --- /dev/null +++ b/compiler/testData/resolve/delegatedProperty/delegationByFun.resolve @@ -0,0 +1,5 @@ +class A + +val a: Int by `foo`foo() + +~foo~fun foo() = A() diff --git a/compiler/testData/resolve/delegatedProperty/delegationByObject.resolve b/compiler/testData/resolve/delegatedProperty/delegationByObject.resolve new file mode 100644 index 00000000000..d4c9230753e --- /dev/null +++ b/compiler/testData/resolve/delegatedProperty/delegationByObject.resolve @@ -0,0 +1,4 @@ +object ~A~A + +val a: Int by `A`A + diff --git a/compiler/testData/resolve/delegatedProperty/delegationByProperty.resolve b/compiler/testData/resolve/delegatedProperty/delegationByProperty.resolve new file mode 100644 index 00000000000..5d48be43b18 --- /dev/null +++ b/compiler/testData/resolve/delegatedProperty/delegationByProperty.resolve @@ -0,0 +1,6 @@ +class A + +~b~val b = A() + +val a: Int by `b`b + diff --git a/compiler/testData/resolve/delegatedProperty/delegationInClass.resolve b/compiler/testData/resolve/delegatedProperty/delegationInClass.resolve new file mode 100644 index 00000000000..9c768a20fb4 --- /dev/null +++ b/compiler/testData/resolve/delegatedProperty/delegationInClass.resolve @@ -0,0 +1,9 @@ +~A~class A { + ~foo~fun foo() = A() +} + +class B { + val a: Int by `A`A().`foo`foo() + val b: Int by `A`A() +} + diff --git a/compiler/testData/resolve/delegatedProperty/localDelegation.resolve b/compiler/testData/resolve/delegatedProperty/localDelegation.resolve new file mode 100644 index 00000000000..3eece029d24 --- /dev/null +++ b/compiler/testData/resolve/delegatedProperty/localDelegation.resolve @@ -0,0 +1,11 @@ +~A~class A { + ~foo~fun foo() = A() +} + +class B { + fun bar() { + val a: Int by `A`A().`foo`foo() + val b: Int by `A`A() + } +} + diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index d29cdebc657..6972c52a9ba 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -1913,6 +1913,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/delegatedProperty/backingField.kt"); } + @TestMetadata("delegatedPropertyOverridedInTrait.kt") + public void testDelegatedPropertyOverridedInTrait() throws Exception { + doTest("compiler/testData/diagnostics/tests/delegatedProperty/delegatedPropertyOverridedInTrait.kt"); + } + @TestMetadata("inTrait.kt") public void testInTrait() throws Exception { doTest("compiler/testData/diagnostics/tests/delegatedProperty/inTrait.kt"); @@ -1923,11 +1928,21 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/delegatedProperty/localVariable.kt"); } + @TestMetadata("propertyDefferedType.kt") + public void testPropertyDefferedType() throws Exception { + doTest("compiler/testData/diagnostics/tests/delegatedProperty/propertyDefferedType.kt"); + } + @TestMetadata("publicDelegatedProperty.kt") public void testPublicDelegatedProperty() throws Exception { doTest("compiler/testData/diagnostics/tests/delegatedProperty/publicDelegatedProperty.kt"); } + @TestMetadata("recursiveType.kt") + public void testRecursiveType() throws Exception { + doTest("compiler/testData/diagnostics/tests/delegatedProperty/recursiveType.kt"); + } + @TestMetadata("redundantGetter.kt") public void testRedundantGetter() throws Exception { doTest("compiler/testData/diagnostics/tests/delegatedProperty/redundantGetter.kt"); @@ -1938,6 +1953,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/delegatedProperty/redundantSetter.kt"); } + @TestMetadata("thisInDelegate.kt") + public void testThisInDelegate() throws Exception { + doTest("compiler/testData/diagnostics/tests/delegatedProperty/thisInDelegate.kt"); + } + } @TestMetadata("compiler/testData/diagnostics/tests/deparenthesize")