Delegated Properties: Analysis adjustments for local delegated properties support
This commit is contained in:
@@ -1055,6 +1055,9 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
|||||||
// We do not want to have getDeferredValue(delegate) here, because delegate value will be read anyway later
|
// We do not want to have getDeferredValue(delegate) here, because delegate value will be read anyway later
|
||||||
visitAssignment(property, getDeferredValue(null), property)
|
visitAssignment(property, getDeferredValue(null), property)
|
||||||
generateInstructions(delegate)
|
generateInstructions(delegate)
|
||||||
|
if (property.isLocal) {
|
||||||
|
generateInitializer(property, createSyntheticValue(property, MagicKind.FAKE_INITIALIZER));
|
||||||
|
}
|
||||||
if (builder.getBoundValue(delegate) != null) {
|
if (builder.getBoundValue(delegate) != null) {
|
||||||
createSyntheticValue(property, MagicKind.VALUE_CONSUMER, delegate)
|
createSyntheticValue(property, MagicKind.VALUE_CONSUMER, delegate)
|
||||||
}
|
}
|
||||||
|
|||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 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.kotlin.descriptors.impl
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||||
|
import org.jetbrains.kotlin.descriptors.VariableAccessorDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
||||||
|
|
||||||
|
sealed class LocalVariableAccessorDescriptor(
|
||||||
|
override val correspondingVariable: LocalVariableDescriptor,
|
||||||
|
isGetter: Boolean
|
||||||
|
) : SimpleFunctionDescriptorImpl(
|
||||||
|
correspondingVariable.containingDeclaration,
|
||||||
|
null,
|
||||||
|
Annotations.EMPTY,
|
||||||
|
Name.special((if (isGetter) "<get-" else "<set-") + correspondingVariable.name + ">"),
|
||||||
|
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||||
|
SourceElement.NO_SOURCE
|
||||||
|
), VariableAccessorDescriptor {
|
||||||
|
class Getter(correspondingVariable: LocalVariableDescriptor) : LocalVariableAccessorDescriptor(correspondingVariable, true)
|
||||||
|
class Setter(correspondingVariable: LocalVariableDescriptor) : LocalVariableAccessorDescriptor(correspondingVariable, false)
|
||||||
|
|
||||||
|
init {
|
||||||
|
val valueParameters =
|
||||||
|
if (isGetter) emptyList() else createValueParameter(Name.identifier("value"), correspondingVariable.type).singletonList()
|
||||||
|
initialize(null, null, emptyList(), valueParameters, correspondingVariable.type, null, Visibilities.LOCAL)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createValueParameter(name: Name, type: KotlinType): ValueParameterDescriptorImpl {
|
||||||
|
return ValueParameterDescriptorImpl(this, null, 0, Annotations.EMPTY, name, type, false, false, false, null, SourceElement.NO_SOURCE)
|
||||||
|
}
|
||||||
|
}
|
||||||
+30
-1
@@ -24,16 +24,33 @@ import org.jetbrains.kotlin.name.Name;
|
|||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
||||||
|
|
||||||
public class LocalVariableDescriptor extends VariableDescriptorWithInitializerImpl {
|
public class LocalVariableDescriptor extends VariableDescriptorWithInitializerImpl implements VariableDescriptorWithAccessors {
|
||||||
|
private final boolean withAccessors;
|
||||||
|
private VariableAccessorDescriptor getter;
|
||||||
|
private VariableAccessorDescriptor setter;
|
||||||
|
|
||||||
public LocalVariableDescriptor(
|
public LocalVariableDescriptor(
|
||||||
@NotNull DeclarationDescriptor containingDeclaration,
|
@NotNull DeclarationDescriptor containingDeclaration,
|
||||||
@NotNull Annotations annotations,
|
@NotNull Annotations annotations,
|
||||||
@NotNull Name name,
|
@NotNull Name name,
|
||||||
@Nullable KotlinType type,
|
@Nullable KotlinType type,
|
||||||
boolean mutable,
|
boolean mutable,
|
||||||
|
boolean withAccessors,
|
||||||
@NotNull SourceElement source
|
@NotNull SourceElement source
|
||||||
) {
|
) {
|
||||||
super(containingDeclaration, annotations, name, type, mutable, source);
|
super(containingDeclaration, annotations, name, type, mutable, source);
|
||||||
|
this.withAccessors = withAccessors;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOutType(KotlinType outType) {
|
||||||
|
super.setOutType(outType);
|
||||||
|
if (withAccessors) {
|
||||||
|
this.getter = new LocalVariableAccessorDescriptor.Getter(this);
|
||||||
|
if (isVar()) {
|
||||||
|
this.setter = new LocalVariableAccessorDescriptor.Setter(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -53,4 +70,16 @@ public class LocalVariableDescriptor extends VariableDescriptorWithInitializerIm
|
|||||||
public Visibility getVisibility() {
|
public Visibility getVisibility() {
|
||||||
return Visibilities.LOCAL;
|
return Visibilities.LOCAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public VariableAccessorDescriptor getGetter() {
|
||||||
|
return getter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public VariableAccessorDescriptor getSetter() {
|
||||||
|
return setter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ class SyntheticFieldDescriptor private constructor(
|
|||||||
accessorDescriptor: PropertyAccessorDescriptor,
|
accessorDescriptor: PropertyAccessorDescriptor,
|
||||||
property: KtProperty
|
property: KtProperty
|
||||||
): LocalVariableDescriptor(accessorDescriptor, Annotations.EMPTY, SyntheticFieldDescriptor.NAME,
|
): LocalVariableDescriptor(accessorDescriptor, Annotations.EMPTY, SyntheticFieldDescriptor.NAME,
|
||||||
propertyDescriptor.type, propertyDescriptor.isVar, property.toSourceElement()) {
|
propertyDescriptor.type, propertyDescriptor.isVar, false, property.toSourceElement()) {
|
||||||
|
|
||||||
constructor(accessorDescriptor: PropertyAccessorDescriptor,
|
constructor(accessorDescriptor: PropertyAccessorDescriptor,
|
||||||
property: KtProperty): this(accessorDescriptor.correspondingProperty, accessorDescriptor, property)
|
property: KtProperty): this(accessorDescriptor.correspondingProperty, accessorDescriptor, property)
|
||||||
|
|||||||
@@ -385,7 +385,7 @@ public interface Errors {
|
|||||||
DiagnosticFactory0<KtPropertyDelegate> ABSTRACT_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtPropertyDelegate> ABSTRACT_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<KtPropertyAccessor> ACCESSOR_FOR_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtPropertyAccessor> ACCESSOR_FOR_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<KtPropertyDelegate> DELEGATED_PROPERTY_IN_INTERFACE = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtPropertyDelegate> DELEGATED_PROPERTY_IN_INTERFACE = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<KtPropertyDelegate> LOCAL_VARIABLE_WITH_DELEGATE = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtPropertyDelegate> SCRIPT_TOP_LEVEL_LOCAL_VARIABLE_WITH_DELEGATE = DiagnosticFactory0.create(ERROR);
|
||||||
|
|
||||||
DiagnosticFactory0<KtProperty> PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
DiagnosticFactory0<KtProperty> PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -214,7 +214,7 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(ABSTRACT_DELEGATED_PROPERTY, "Delegated property cannot be abstract");
|
MAP.put(ABSTRACT_DELEGATED_PROPERTY, "Delegated property cannot be abstract");
|
||||||
MAP.put(ACCESSOR_FOR_DELEGATED_PROPERTY, "Delegated property cannot have accessors with non-default implementations");
|
MAP.put(ACCESSOR_FOR_DELEGATED_PROPERTY, "Delegated property cannot have accessors with non-default implementations");
|
||||||
MAP.put(DELEGATED_PROPERTY_IN_INTERFACE, "Delegated properties are not allowed in interfaces");
|
MAP.put(DELEGATED_PROPERTY_IN_INTERFACE, "Delegated properties are not allowed in interfaces");
|
||||||
MAP.put(LOCAL_VARIABLE_WITH_DELEGATE, "Local variables are not allowed to have delegates");
|
MAP.put(SCRIPT_TOP_LEVEL_LOCAL_VARIABLE_WITH_DELEGATE, "Top-level local variables in scripts are not allowed to have delegates");
|
||||||
|
|
||||||
MAP.put(INAPPLICABLE_LATEINIT_MODIFIER, "''lateinit'' modifier {0}", STRING);
|
MAP.put(INAPPLICABLE_LATEINIT_MODIFIER, "''lateinit'' modifier {0}", STRING);
|
||||||
|
|
||||||
|
|||||||
@@ -123,10 +123,10 @@ public interface BindingContext {
|
|||||||
WritableSlice<KtExpression, ResolvedCall<FunctionDescriptor>> LOOP_RANGE_HAS_NEXT_RESOLVED_CALL = Slices.createSimpleSlice();
|
WritableSlice<KtExpression, ResolvedCall<FunctionDescriptor>> LOOP_RANGE_HAS_NEXT_RESOLVED_CALL = Slices.createSimpleSlice();
|
||||||
WritableSlice<KtExpression, ResolvedCall<FunctionDescriptor>> LOOP_RANGE_NEXT_RESOLVED_CALL = Slices.createSimpleSlice();
|
WritableSlice<KtExpression, ResolvedCall<FunctionDescriptor>> LOOP_RANGE_NEXT_RESOLVED_CALL = Slices.createSimpleSlice();
|
||||||
|
|
||||||
WritableSlice<PropertyAccessorDescriptor, ResolvedCall<FunctionDescriptor>> DELEGATED_PROPERTY_RESOLVED_CALL = Slices.createSimpleSlice();
|
WritableSlice<VariableAccessorDescriptor, ResolvedCall<FunctionDescriptor>> DELEGATED_PROPERTY_RESOLVED_CALL = Slices.createSimpleSlice();
|
||||||
WritableSlice<PropertyAccessorDescriptor, Call> DELEGATED_PROPERTY_CALL = Slices.createSimpleSlice();
|
WritableSlice<VariableAccessorDescriptor, Call> DELEGATED_PROPERTY_CALL = Slices.createSimpleSlice();
|
||||||
|
|
||||||
WritableSlice<PropertyDescriptor, ResolvedCall<FunctionDescriptor>> DELEGATED_PROPERTY_PD_RESOLVED_CALL = Slices.createSimpleSlice();
|
WritableSlice<VariableDescriptorWithAccessors, ResolvedCall<FunctionDescriptor>> DELEGATED_PROPERTY_PD_RESOLVED_CALL = Slices.createSimpleSlice();
|
||||||
|
|
||||||
WritableSlice<KtDestructuringDeclarationEntry, ResolvedCall<FunctionDescriptor>> COMPONENT_RESOLVED_CALL = Slices.createSimpleSlice();
|
WritableSlice<KtDestructuringDeclarationEntry, ResolvedCall<FunctionDescriptor>> COMPONENT_RESOLVED_CALL = Slices.createSimpleSlice();
|
||||||
|
|
||||||
|
|||||||
@@ -696,34 +696,12 @@ public class BodyResolver {
|
|||||||
@NotNull KtExpression delegateExpression,
|
@NotNull KtExpression delegateExpression,
|
||||||
@NotNull LexicalScope propertyHeaderScope
|
@NotNull LexicalScope propertyHeaderScope
|
||||||
) {
|
) {
|
||||||
KtPropertyAccessor getter = property.getGetter();
|
delegatedPropertyResolver.resolvePropertyDelegate(outerDataFlowInfo,
|
||||||
if (getter != null && getter.hasBody()) {
|
property,
|
||||||
trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(getter));
|
propertyDescriptor,
|
||||||
}
|
delegateExpression,
|
||||||
|
propertyHeaderScope,
|
||||||
KtPropertyAccessor setter = property.getSetter();
|
trace);
|
||||||
if (setter != null && setter.hasBody()) {
|
|
||||||
trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(setter));
|
|
||||||
}
|
|
||||||
|
|
||||||
LexicalScope delegateFunctionsScope = ScopeUtils.makeScopeForDelegateConventionFunctions(propertyHeaderScope, propertyDescriptor);
|
|
||||||
|
|
||||||
LexicalScope initializerScope = ScopeUtils.makeScopeForPropertyInitializer(propertyHeaderScope, propertyDescriptor);
|
|
||||||
|
|
||||||
KotlinType delegateType = delegatedPropertyResolver.resolveDelegateExpression(
|
|
||||||
delegateExpression, property, propertyDescriptor, initializerScope, trace,
|
|
||||||
outerDataFlowInfo);
|
|
||||||
|
|
||||||
delegatedPropertyResolver.resolveDelegatedPropertyGetMethod(propertyDescriptor, delegateExpression, delegateType,
|
|
||||||
trace, delegateFunctionsScope);
|
|
||||||
|
|
||||||
if (property.isVar()) {
|
|
||||||
delegatedPropertyResolver.resolveDelegatedPropertySetMethod(propertyDescriptor, delegateExpression, delegateType,
|
|
||||||
trace, delegateFunctionsScope);
|
|
||||||
}
|
|
||||||
|
|
||||||
delegatedPropertyResolver.resolveDelegatedPropertyPDMethod(propertyDescriptor, delegateExpression, delegateType,
|
|
||||||
trace, delegateFunctionsScope);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resolvePropertyInitializer(
|
private void resolvePropertyInitializer(
|
||||||
|
|||||||
@@ -400,6 +400,14 @@ class DeclarationsChecker(
|
|||||||
exposedChecker.checkProperty(property, propertyDescriptor)
|
exposedChecker.checkProperty(property, propertyDescriptor)
|
||||||
checkPropertyTypeParametersAreUsedInReceiverType(propertyDescriptor)
|
checkPropertyTypeParametersAreUsedInReceiverType(propertyDescriptor)
|
||||||
checkImplicitCallableType(property, propertyDescriptor)
|
checkImplicitCallableType(property, propertyDescriptor)
|
||||||
|
checkDelegatedPropertyInScript(property)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkDelegatedPropertyInScript(property: KtProperty) {
|
||||||
|
val delegate = property.delegate
|
||||||
|
if (delegate != null && KtPsiUtil.isScriptDeclaration(property)) {
|
||||||
|
trace.report(SCRIPT_TOP_LEVEL_LOCAL_VARIABLE_WITH_DELEGATE.on(delegate))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkPropertyTypeParametersAreUsedInReceiverType(descriptor: PropertyDescriptor) {
|
private fun checkPropertyTypeParametersAreUsedInReceiverType(descriptor: PropertyDescriptor) {
|
||||||
|
|||||||
@@ -85,48 +85,93 @@ public class DelegatedPropertyResolver {
|
|||||||
this.expressionTypingServices = expressionTypingServices;
|
this.expressionTypingServices = expressionTypingServices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void resolvePropertyDelegate(
|
||||||
|
@NotNull DataFlowInfo outerDataFlowInfo,
|
||||||
|
@NotNull KtProperty property,
|
||||||
|
@NotNull VariableDescriptorWithAccessors variableDescriptor,
|
||||||
|
@NotNull KtExpression delegateExpression,
|
||||||
|
@NotNull LexicalScope propertyHeaderScope,
|
||||||
|
@NotNull BindingTrace trace
|
||||||
|
) {
|
||||||
|
KtPropertyAccessor getter = property.getGetter();
|
||||||
|
if (getter != null && getter.hasBody()) {
|
||||||
|
trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(getter));
|
||||||
|
}
|
||||||
|
|
||||||
|
KtPropertyAccessor setter = property.getSetter();
|
||||||
|
if (setter != null && setter.hasBody()) {
|
||||||
|
trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(setter));
|
||||||
|
}
|
||||||
|
|
||||||
|
LexicalScope delegateFunctionsScope;
|
||||||
|
LexicalScope initializerScope;
|
||||||
|
|
||||||
|
if (variableDescriptor instanceof PropertyDescriptor) {
|
||||||
|
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variableDescriptor;
|
||||||
|
delegateFunctionsScope = ScopeUtils.makeScopeForDelegateConventionFunctions(propertyHeaderScope, propertyDescriptor);
|
||||||
|
initializerScope = ScopeUtils.makeScopeForPropertyInitializer(propertyHeaderScope, propertyDescriptor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delegateFunctionsScope = initializerScope = propertyHeaderScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
KotlinType delegateType = resolveDelegateExpression(delegateExpression,
|
||||||
|
property,
|
||||||
|
variableDescriptor,
|
||||||
|
initializerScope,
|
||||||
|
trace,
|
||||||
|
outerDataFlowInfo);
|
||||||
|
|
||||||
|
resolveDelegatedPropertyGetMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope);
|
||||||
|
if (property.isVar()) {
|
||||||
|
resolveDelegatedPropertySetMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveDelegatedPropertyPDMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public KotlinType getDelegatedPropertyGetMethodReturnType(
|
public KotlinType getDelegatedPropertyGetMethodReturnType(
|
||||||
@NotNull PropertyDescriptor propertyDescriptor,
|
@NotNull VariableDescriptorWithAccessors variableDescriptor,
|
||||||
@NotNull KtExpression delegateExpression,
|
@NotNull KtExpression delegateExpression,
|
||||||
@NotNull KotlinType delegateType,
|
@NotNull KotlinType delegateType,
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@NotNull LexicalScope delegateFunctionsScope
|
@NotNull LexicalScope delegateFunctionsScope
|
||||||
) {
|
) {
|
||||||
resolveDelegatedPropertyConventionMethod(propertyDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, true);
|
resolveDelegatedPropertyConventionMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, true);
|
||||||
ResolvedCall<FunctionDescriptor> resolvedCall =
|
ResolvedCall<FunctionDescriptor> resolvedCall =
|
||||||
trace.getBindingContext().get(DELEGATED_PROPERTY_RESOLVED_CALL, propertyDescriptor.getGetter());
|
trace.getBindingContext().get(DELEGATED_PROPERTY_RESOLVED_CALL, variableDescriptor.getGetter());
|
||||||
return resolvedCall != null ? resolvedCall.getResultingDescriptor().getReturnType() : null;
|
return resolvedCall != null ? resolvedCall.getResultingDescriptor().getReturnType() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resolveDelegatedPropertyGetMethod(
|
public void resolveDelegatedPropertyGetMethod(
|
||||||
@NotNull PropertyDescriptor propertyDescriptor,
|
@NotNull VariableDescriptorWithAccessors variableDescriptor,
|
||||||
@NotNull KtExpression delegateExpression,
|
@NotNull KtExpression delegateExpression,
|
||||||
@NotNull KotlinType delegateType,
|
@NotNull KotlinType delegateType,
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@NotNull LexicalScope delegateFunctionsScope
|
@NotNull LexicalScope delegateFunctionsScope
|
||||||
) {
|
) {
|
||||||
KotlinType returnType = getDelegatedPropertyGetMethodReturnType(
|
KotlinType returnType = getDelegatedPropertyGetMethodReturnType(
|
||||||
propertyDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope);
|
variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope);
|
||||||
KotlinType propertyType = propertyDescriptor.getType();
|
KotlinType propertyType = variableDescriptor.getType();
|
||||||
|
|
||||||
/* Do not check return type of get() method of delegate for properties with DeferredType because property type is taken from it */
|
/* Do not check return type of get() method of delegate for properties with DeferredType because property type is taken from it */
|
||||||
if (!(propertyType instanceof DeferredType) && returnType != null && !KotlinTypeChecker.DEFAULT.isSubtypeOf(returnType, propertyType)) {
|
if (!(propertyType instanceof DeferredType) && returnType != null && !KotlinTypeChecker.DEFAULT.isSubtypeOf(returnType, propertyType)) {
|
||||||
Call call = trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, propertyDescriptor.getGetter());
|
Call call = trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, variableDescriptor.getGetter());
|
||||||
assert call != null : "Call should exists for " + propertyDescriptor.getGetter();
|
assert call != null : "Call should exists for " + variableDescriptor.getGetter();
|
||||||
trace.report(DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH
|
trace.report(DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH
|
||||||
.on(delegateExpression, renderCall(call, trace.getBindingContext()), propertyDescriptor.getType(), returnType));
|
.on(delegateExpression, renderCall(call, trace.getBindingContext()), variableDescriptor.getType(), returnType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resolveDelegatedPropertySetMethod(
|
public void resolveDelegatedPropertySetMethod(
|
||||||
@NotNull PropertyDescriptor propertyDescriptor,
|
@NotNull VariableDescriptorWithAccessors variableDescriptor,
|
||||||
@NotNull KtExpression delegateExpression,
|
@NotNull KtExpression delegateExpression,
|
||||||
@NotNull KotlinType delegateType,
|
@NotNull KotlinType delegateType,
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@NotNull LexicalScope delegateFunctionsScope
|
@NotNull LexicalScope delegateFunctionsScope
|
||||||
) {
|
) {
|
||||||
resolveDelegatedPropertyConventionMethod(propertyDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, false);
|
resolveDelegatedPropertyConventionMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -135,7 +180,7 @@ public class DelegatedPropertyResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void resolveDelegatedPropertyPDMethod(
|
public void resolveDelegatedPropertyPDMethod(
|
||||||
@NotNull PropertyDescriptor propertyDescriptor,
|
@NotNull VariableDescriptorWithAccessors variableDescriptor,
|
||||||
@NotNull KtExpression delegateExpression,
|
@NotNull KtExpression delegateExpression,
|
||||||
@NotNull KotlinType delegateType,
|
@NotNull KotlinType delegateType,
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@@ -168,19 +213,19 @@ public class DelegatedPropertyResolver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace.record(DELEGATED_PROPERTY_PD_RESOLVED_CALL, propertyDescriptor, functionResults.getResultingCall());
|
trace.record(DELEGATED_PROPERTY_PD_RESOLVED_CALL, variableDescriptor, functionResults.getResultingCall());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resolve getValue() or setValue() methods from delegate */
|
/* Resolve getValue() or setValue() methods from delegate */
|
||||||
private void resolveDelegatedPropertyConventionMethod(
|
private void resolveDelegatedPropertyConventionMethod(
|
||||||
@NotNull PropertyDescriptor propertyDescriptor,
|
@NotNull VariableDescriptorWithAccessors propertyDescriptor,
|
||||||
@NotNull KtExpression delegateExpression,
|
@NotNull KtExpression delegateExpression,
|
||||||
@NotNull KotlinType delegateType,
|
@NotNull KotlinType delegateType,
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@NotNull LexicalScope delegateFunctionsScope,
|
@NotNull LexicalScope delegateFunctionsScope,
|
||||||
boolean isGet
|
boolean isGet
|
||||||
) {
|
) {
|
||||||
PropertyAccessorDescriptor accessor = isGet ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
|
VariableAccessorDescriptor accessor = isGet ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
|
||||||
assert accessor != null : "Delegated property should have getter/setter " + propertyDescriptor + " " + delegateExpression.getText();
|
assert accessor != null : "Delegated property should have getter/setter " + propertyDescriptor + " " + delegateExpression.getText();
|
||||||
|
|
||||||
if (trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, accessor) != null) return;
|
if (trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, accessor) != null) return;
|
||||||
@@ -229,7 +274,7 @@ public class DelegatedPropertyResolver {
|
|||||||
|
|
||||||
/* Resolve getValue() or setValue() methods from delegate */
|
/* Resolve getValue() or setValue() methods from delegate */
|
||||||
public OverloadResolutionResults<FunctionDescriptor> getDelegatedPropertyConventionMethod(
|
public OverloadResolutionResults<FunctionDescriptor> getDelegatedPropertyConventionMethod(
|
||||||
@NotNull PropertyDescriptor propertyDescriptor,
|
@NotNull VariableDescriptorWithAccessors propertyDescriptor,
|
||||||
@NotNull KtExpression delegateExpression,
|
@NotNull KtExpression delegateExpression,
|
||||||
@NotNull KotlinType delegateType,
|
@NotNull KotlinType delegateType,
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@@ -237,7 +282,7 @@ public class DelegatedPropertyResolver {
|
|||||||
boolean isGet,
|
boolean isGet,
|
||||||
boolean isComplete
|
boolean isComplete
|
||||||
) {
|
) {
|
||||||
PropertyAccessorDescriptor accessor = isGet ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
|
VariableAccessorDescriptor accessor = isGet ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
|
||||||
assert accessor != null : "Delegated property should have getter/setter " + propertyDescriptor + " " + delegateExpression.getText();
|
assert accessor != null : "Delegated property should have getter/setter " + propertyDescriptor + " " + delegateExpression.getText();
|
||||||
|
|
||||||
KotlinType expectedType = isComplete && isGet && !(propertyDescriptor.getType() instanceof DeferredType)
|
KotlinType expectedType = isComplete && isGet && !(propertyDescriptor.getType() instanceof DeferredType)
|
||||||
@@ -326,7 +371,7 @@ public class DelegatedPropertyResolver {
|
|||||||
public KotlinType resolveDelegateExpression(
|
public KotlinType resolveDelegateExpression(
|
||||||
@NotNull KtExpression delegateExpression,
|
@NotNull KtExpression delegateExpression,
|
||||||
@NotNull KtProperty property,
|
@NotNull KtProperty property,
|
||||||
@NotNull PropertyDescriptor propertyDescriptor,
|
@NotNull VariableDescriptorWithAccessors variableDescriptor,
|
||||||
@NotNull LexicalScope scopeForDelegate,
|
@NotNull LexicalScope scopeForDelegate,
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@NotNull DataFlowInfo dataFlowInfo
|
@NotNull DataFlowInfo dataFlowInfo
|
||||||
@@ -334,7 +379,7 @@ public class DelegatedPropertyResolver {
|
|||||||
TemporaryBindingTrace traceToResolveDelegatedProperty = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property");
|
TemporaryBindingTrace traceToResolveDelegatedProperty = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property");
|
||||||
KtExpression calleeExpression = CallUtilKt.getCalleeExpressionIfAny(delegateExpression);
|
KtExpression calleeExpression = CallUtilKt.getCalleeExpressionIfAny(delegateExpression);
|
||||||
ConstraintSystemCompleter completer = createConstraintSystemCompleter(
|
ConstraintSystemCompleter completer = createConstraintSystemCompleter(
|
||||||
property, propertyDescriptor, delegateExpression, scopeForDelegate, trace);
|
property, variableDescriptor, delegateExpression, scopeForDelegate, trace);
|
||||||
if (calleeExpression != null) {
|
if (calleeExpression != null) {
|
||||||
traceToResolveDelegatedProperty.record(CONSTRAINT_SYSTEM_COMPLETER, calleeExpression, completer);
|
traceToResolveDelegatedProperty.record(CONSTRAINT_SYSTEM_COMPLETER, calleeExpression, completer);
|
||||||
}
|
}
|
||||||
@@ -352,13 +397,13 @@ public class DelegatedPropertyResolver {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private ConstraintSystemCompleter createConstraintSystemCompleter(
|
private ConstraintSystemCompleter createConstraintSystemCompleter(
|
||||||
@NotNull KtProperty property,
|
@NotNull KtProperty property,
|
||||||
@NotNull final PropertyDescriptor propertyDescriptor,
|
@NotNull final VariableDescriptorWithAccessors variableDescriptor,
|
||||||
@NotNull final KtExpression delegateExpression,
|
@NotNull final KtExpression delegateExpression,
|
||||||
@NotNull LexicalScope scopeForDelegate,
|
@NotNull LexicalScope scopeForDelegate,
|
||||||
@NotNull final BindingTrace trace
|
@NotNull final BindingTrace trace
|
||||||
) {
|
) {
|
||||||
final LexicalScope delegateFunctionsScope = ScopeUtils.makeScopeForDelegateConventionFunctions(scopeForDelegate, propertyDescriptor);
|
final LexicalScope delegateFunctionsScope = ScopeUtils.makeScopeForDelegateConventionFunctions(scopeForDelegate, variableDescriptor);
|
||||||
final KotlinType expectedType = property.getTypeReference() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE;
|
final KotlinType expectedType = property.getTypeReference() != null ? variableDescriptor.getType() : NO_EXPECTED_TYPE;
|
||||||
return new ConstraintSystemCompleter() {
|
return new ConstraintSystemCompleter() {
|
||||||
@Override
|
@Override
|
||||||
public void completeConstraintSystem(
|
public void completeConstraintSystem(
|
||||||
@@ -375,7 +420,7 @@ public class DelegatedPropertyResolver {
|
|||||||
TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods");
|
TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods");
|
||||||
OverloadResolutionResults<FunctionDescriptor>
|
OverloadResolutionResults<FunctionDescriptor>
|
||||||
getMethodResults = getDelegatedPropertyConventionMethod(
|
getMethodResults = getDelegatedPropertyConventionMethod(
|
||||||
propertyDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, delegateFunctionsScope,
|
variableDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, delegateFunctionsScope,
|
||||||
true, false
|
true, false
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -390,16 +435,16 @@ public class DelegatedPropertyResolver {
|
|||||||
}
|
}
|
||||||
addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, descriptor);
|
addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, descriptor);
|
||||||
}
|
}
|
||||||
if (!propertyDescriptor.isVar()) return;
|
if (!variableDescriptor.isVar()) return;
|
||||||
|
|
||||||
// For the case: 'val v by d' (no declared type).
|
// For the case: 'val v by d' (no declared type).
|
||||||
// When we add a constraint for 'set' method for delegated expression 'd' we use a type of the declared variable 'v'.
|
// When we add a constraint for 'set' method for delegated expression 'd' we use a type of the declared variable 'v'.
|
||||||
// But if the type isn't known yet, the constraint shouldn't be added (we try to infer the type of 'v' here as well).
|
// But if the type isn't known yet, the constraint shouldn't be added (we try to infer the type of 'v' here as well).
|
||||||
if (propertyDescriptor.getReturnType() instanceof DeferredType) return;
|
if (variableDescriptor.getReturnType() instanceof DeferredType) return;
|
||||||
|
|
||||||
OverloadResolutionResults<FunctionDescriptor>
|
OverloadResolutionResults<FunctionDescriptor>
|
||||||
setMethodResults = getDelegatedPropertyConventionMethod(
|
setMethodResults = getDelegatedPropertyConventionMethod(
|
||||||
propertyDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, delegateFunctionsScope,
|
variableDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, delegateFunctionsScope,
|
||||||
false, false
|
false, false
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -432,8 +477,8 @@ public class DelegatedPropertyResolver {
|
|||||||
TypeSubstitutor typeVariableSubstitutor,
|
TypeSubstitutor typeVariableSubstitutor,
|
||||||
FunctionDescriptor resultingDescriptor
|
FunctionDescriptor resultingDescriptor
|
||||||
) {
|
) {
|
||||||
ReceiverParameterDescriptor extensionReceiver = propertyDescriptor.getExtensionReceiverParameter();
|
ReceiverParameterDescriptor extensionReceiver = variableDescriptor.getExtensionReceiverParameter();
|
||||||
ReceiverParameterDescriptor dispatchReceiver = propertyDescriptor.getDispatchReceiverParameter();
|
ReceiverParameterDescriptor dispatchReceiver = variableDescriptor.getDispatchReceiverParameter();
|
||||||
KotlinType typeOfThis =
|
KotlinType typeOfThis =
|
||||||
extensionReceiver != null ? extensionReceiver.getType() :
|
extensionReceiver != null ? extensionReceiver.getType() :
|
||||||
dispatchReceiver != null ? dispatchReceiver.getType() :
|
dispatchReceiver != null ? dispatchReceiver.getType() :
|
||||||
|
|||||||
@@ -655,6 +655,7 @@ public class DescriptorResolver {
|
|||||||
KtPsiUtil.safeName(parameter.getName()),
|
KtPsiUtil.safeName(parameter.getName()),
|
||||||
type,
|
type,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
KotlinSourceElementKt.toSourceElement(parameter)
|
KotlinSourceElementKt.toSourceElement(parameter)
|
||||||
);
|
);
|
||||||
trace.record(BindingContext.VALUE_PARAMETER, parameter, variableDescriptor);
|
trace.record(BindingContext.VALUE_PARAMETER, parameter, variableDescriptor);
|
||||||
|
|||||||
@@ -35,12 +35,12 @@ import org.jetbrains.kotlin.types.expressions.*
|
|||||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.noTypeInfo
|
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.noTypeInfo
|
||||||
|
|
||||||
class LocalVariableResolver(
|
class LocalVariableResolver(
|
||||||
private val expressionTypingServices: ExpressionTypingServices,
|
|
||||||
private val modifiersChecker: ModifiersChecker,
|
private val modifiersChecker: ModifiersChecker,
|
||||||
private val identifierChecker: IdentifierChecker,
|
private val identifierChecker: IdentifierChecker,
|
||||||
private val dataFlowAnalyzer: DataFlowAnalyzer,
|
private val dataFlowAnalyzer: DataFlowAnalyzer,
|
||||||
private val annotationResolver: AnnotationResolver,
|
private val annotationResolver: AnnotationResolver,
|
||||||
private val variableTypeResolver: VariableTypeResolver
|
private val variableTypeResolver: VariableTypeResolver,
|
||||||
|
private val delegatedPropertyResolver: DelegatedPropertyResolver
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun process(
|
fun process(
|
||||||
@@ -65,13 +65,18 @@ class LocalVariableResolver(
|
|||||||
context.trace.report(LOCAL_VARIABLE_WITH_SETTER.on(setter))
|
context.trace.report(LOCAL_VARIABLE_WITH_SETTER.on(setter))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val propertyDescriptor = resolveLocalVariableDescriptor(scope, property, context.dataFlowInfo, context.trace)
|
||||||
|
|
||||||
val delegateExpression = property.delegateExpression
|
val delegateExpression = property.delegateExpression
|
||||||
if (delegateExpression != null) {
|
if (delegateExpression != null && propertyDescriptor is VariableDescriptorWithAccessors) {
|
||||||
expressionTypingServices.getTypeInfo(delegateExpression, context)
|
delegatedPropertyResolver.resolvePropertyDelegate(typingContext.dataFlowInfo,
|
||||||
context.trace.report(LOCAL_VARIABLE_WITH_DELEGATE.on(property.delegate!!))
|
property,
|
||||||
|
propertyDescriptor,
|
||||||
|
delegateExpression,
|
||||||
|
typingContext.scope,
|
||||||
|
typingContext.trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
val propertyDescriptor = resolveLocalVariableDescriptor(scope, property, context.dataFlowInfo, context.trace)
|
|
||||||
val initializer = property.initializer
|
val initializer = property.initializer
|
||||||
var typeInfo: KotlinTypeInfo
|
var typeInfo: KotlinTypeInfo
|
||||||
if (initializer != null) {
|
if (initializer != null) {
|
||||||
@@ -167,12 +172,14 @@ class LocalVariableResolver(
|
|||||||
type: KotlinType?,
|
type: KotlinType?,
|
||||||
trace: BindingTrace
|
trace: BindingTrace
|
||||||
): LocalVariableDescriptor {
|
): LocalVariableDescriptor {
|
||||||
|
val hasDelegate = variable is KtProperty && variable.hasDelegate();
|
||||||
val variableDescriptor = LocalVariableDescriptor(
|
val variableDescriptor = LocalVariableDescriptor(
|
||||||
scope.ownerDescriptor,
|
scope.ownerDescriptor,
|
||||||
annotationResolver.resolveAnnotationsWithArguments(scope, variable.modifierList, trace),
|
annotationResolver.resolveAnnotationsWithArguments(scope, variable.modifierList, trace),
|
||||||
KtPsiUtil.safeName(variable.name),
|
KtPsiUtil.safeName(variable.name),
|
||||||
type,
|
type,
|
||||||
variable.isVar,
|
variable.isVar,
|
||||||
|
hasDelegate,
|
||||||
variable.toSourceElement()
|
variable.toSourceElement()
|
||||||
)
|
)
|
||||||
trace.record(BindingContext.VARIABLE, variable, variableDescriptor)
|
trace.record(BindingContext.VARIABLE, variable, variableDescriptor)
|
||||||
|
|||||||
+1
-1
@@ -202,7 +202,7 @@ private fun bindFunctionReference(expression: KtCallableReferenceExpression, typ
|
|||||||
|
|
||||||
private fun bindPropertyReference(expression: KtCallableReferenceExpression, referenceType: KotlinType, context: ResolutionContext<*>) {
|
private fun bindPropertyReference(expression: KtCallableReferenceExpression, referenceType: KotlinType, context: ResolutionContext<*>) {
|
||||||
val localVariable = LocalVariableDescriptor(context.scope.ownerDescriptor, Annotations.EMPTY, Name.special("<anonymous>"),
|
val localVariable = LocalVariableDescriptor(context.scope.ownerDescriptor, Annotations.EMPTY, Name.special("<anonymous>"),
|
||||||
referenceType, /* mutable = */ false, expression.toSourceElement())
|
referenceType, /* mutable = */ false, false, expression.toSourceElement())
|
||||||
|
|
||||||
context.trace.record(BindingContext.VARIABLE, expression, localVariable)
|
context.trace.record(BindingContext.VARIABLE, expression, localVariable)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-1
@@ -60,7 +60,7 @@ public class ExpressionTypingComponents {
|
|||||||
/*package*/ DeclarationsCheckerBuilder declarationsCheckerBuilder;
|
/*package*/ DeclarationsCheckerBuilder declarationsCheckerBuilder;
|
||||||
/*package*/ LocalVariableResolver localVariableResolver;
|
/*package*/ LocalVariableResolver localVariableResolver;
|
||||||
/*package*/ LookupTracker lookupTracker;
|
/*package*/ LookupTracker lookupTracker;
|
||||||
|
/*package*/ DelegatedPropertyResolver delegatedPropertyResolver;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public void setGlobalContext(@NotNull GlobalContext globalContext) {
|
public void setGlobalContext(@NotNull GlobalContext globalContext) {
|
||||||
@@ -201,4 +201,9 @@ public class ExpressionTypingComponents {
|
|||||||
public void setLookupTracker(@NotNull LookupTracker lookupTracker) {
|
public void setLookupTracker(@NotNull LookupTracker lookupTracker) {
|
||||||
this.lookupTracker = lookupTracker;
|
this.lookupTracker = lookupTracker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public void setDelegatedPropertyResolver(DelegatedPropertyResolver delegatedPropertyResolver) {
|
||||||
|
this.delegatedPropertyResolver = delegatedPropertyResolver;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,7 @@ import kotlin.Unit;
|
|||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
|
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
|
||||||
import org.jetbrains.kotlin.utils.Printer;
|
import org.jetbrains.kotlin.utils.Printer;
|
||||||
|
|
||||||
public final class ScopeUtils {
|
public final class ScopeUtils {
|
||||||
@@ -69,10 +66,10 @@ public final class ScopeUtils {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static LexicalScope makeScopeForDelegateConventionFunctions(
|
public static LexicalScope makeScopeForDelegateConventionFunctions(
|
||||||
@NotNull LexicalScope parent,
|
@NotNull LexicalScope parent,
|
||||||
@NotNull PropertyDescriptor propertyDescriptor
|
@NotNull VariableDescriptorWithAccessors variableDescriptor
|
||||||
) {
|
) {
|
||||||
// todo: very strange scope!
|
// todo: very strange scope!
|
||||||
return new LexicalScopeImpl(parent, propertyDescriptor, true, propertyDescriptor.getExtensionReceiverParameter(),
|
return new LexicalScopeImpl(parent, variableDescriptor, true, variableDescriptor.getExtensionReceiverParameter(),
|
||||||
LexicalScopeKind.PROPERTY_DELEGATE_METHOD
|
LexicalScopeKind.PROPERTY_DELEGATE_METHOD
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
== Delegate ==
|
||||||
|
class Delegate {
|
||||||
|
operator fun getValue(t: Any?, p: KProperty<*>): Int = 1
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
L1:
|
||||||
|
<END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== getValue ==
|
||||||
|
operator fun getValue(t: Any?, p: KProperty<*>): Int = 1
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
v(t: Any?)
|
||||||
|
magic[FAKE_INITIALIZER](t: Any?) -> <v0>
|
||||||
|
w(t|<v0>)
|
||||||
|
v(p: KProperty<*>)
|
||||||
|
magic[FAKE_INITIALIZER](p: KProperty<*>) -> <v1>
|
||||||
|
w(p|<v1>)
|
||||||
|
r(1) -> <v2>
|
||||||
|
ret(*|<v2>) L1
|
||||||
|
L1:
|
||||||
|
<END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun foo(): Int {
|
||||||
|
val prop: Int by Delegate()
|
||||||
|
return prop
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
2 mark({ val prop: Int by Delegate() return prop })
|
||||||
|
v(val prop: Int by Delegate())
|
||||||
|
magic[UNRECOGNIZED_WRITE_RHS](val prop: Int by Delegate()) -> <v0>
|
||||||
|
w(prop|<v0>)
|
||||||
|
mark(Delegate())
|
||||||
|
call(Delegate(), <init>) -> <v1>
|
||||||
|
magic[FAKE_INITIALIZER](val prop: Int by Delegate()) -> <v2>
|
||||||
|
w(prop|<v2>)
|
||||||
|
magic[VALUE_CONSUMER](val prop: Int by Delegate()|<v1>) -> <v3>
|
||||||
|
r(prop) -> <v4>
|
||||||
|
ret(*|<v4>) L1
|
||||||
|
L1:
|
||||||
|
1 <END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
class Delegate {
|
||||||
|
operator fun getValue(t: Any?, p: KProperty<*>): Int = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(): Int {
|
||||||
|
val prop: Int by Delegate()
|
||||||
|
return prop
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
== Delegate ==
|
||||||
|
class Delegate {
|
||||||
|
operator fun getValue(t: Any?, p: KProperty<*>): Int = 1
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
=====================
|
||||||
|
== getValue ==
|
||||||
|
operator fun getValue(t: Any?, p: KProperty<*>): Int = 1
|
||||||
|
---------------------
|
||||||
|
<v0>: * NEW: magic[FAKE_INITIALIZER](t: Any?) -> <v0>
|
||||||
|
<v1>: {<: KProperty<*>} NEW: magic[FAKE_INITIALIZER](p: KProperty<*>) -> <v1>
|
||||||
|
1 <v2>: Int NEW: r(1) -> <v2>
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun foo(): Int {
|
||||||
|
val prop: Int by Delegate()
|
||||||
|
return prop
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
<v0>: Int NEW: magic[UNRECOGNIZED_WRITE_RHS](val prop: Int by Delegate()) -> <v0>
|
||||||
|
<v2>: Int NEW: magic[FAKE_INITIALIZER](val prop: Int by Delegate()) -> <v2>
|
||||||
|
<v3>: * NEW: magic[VALUE_CONSUMER](val prop: Int by Delegate()|<v1>) -> <v3>
|
||||||
|
Delegate() <v1>: * NEW: call(Delegate(), <init>) -> <v1>
|
||||||
|
prop <v4>: Int NEW: r(prop) -> <v4>
|
||||||
|
return prop !<v5>: *
|
||||||
|
{ val prop: Int by Delegate() return prop } !<v5>: * COPY
|
||||||
|
=====================
|
||||||
@@ -3,13 +3,13 @@
|
|||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
class Local {
|
class Local {
|
||||||
fun foo() {
|
fun foo() {
|
||||||
val a: Int <!LOCAL_VARIABLE_WITH_DELEGATE!>by Delegate()<!>
|
val a: Int by Delegate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Delegate {
|
class Delegate {
|
||||||
fun getValue(t: Any?, p: KProperty<*>): Int {
|
operator fun getValue(t: Any?, p: KProperty<*>): Int {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@ package
|
|||||||
public final class Delegate {
|
public final class Delegate {
|
||||||
public constructor Delegate()
|
public constructor Delegate()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public final fun getValue(/*0*/ t: kotlin.Any?, /*1*/ p: kotlin.reflect.KProperty<*>): kotlin.Int
|
public final operator fun getValue(/*0*/ t: kotlin.Any?, /*1*/ p: kotlin.reflect.KProperty<*>): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||||
|
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
class Delegate {
|
||||||
|
operator fun getValue(t: Any?, p: KProperty<*>): Int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val a: Int <!SCRIPT_TOP_LEVEL_LOCAL_VARIABLE_WITH_DELEGATE!>by Delegate()<!>
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
val a: Int by Delegate()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a: Int by Delegate()
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public final class TopLevelVariable {
|
||||||
|
public constructor TopLevelVariable(/*0*/ args: kotlin.Array<kotlin.String>)
|
||||||
|
public final val a: kotlin.Int
|
||||||
|
public final val args: kotlin.Array<kotlin.String>
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final fun foo(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
public final class Delegate {
|
||||||
|
public constructor Delegate()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final operator fun getValue(/*0*/ t: kotlin.Any?, /*1*/ p: kotlin.reflect.KProperty<*>): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Foo {
|
||||||
|
public constructor Foo()
|
||||||
|
public final val a: kotlin.Int
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -474,6 +474,12 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("localDelegatedVal.kt")
|
||||||
|
public void testLocalDelegatedVal() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localDelegatedVal.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("localFunction.kt")
|
@TestMetadata("localFunction.kt")
|
||||||
public void testLocalFunction() throws Exception {
|
public void testLocalFunction() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localFunction.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localFunction.kt");
|
||||||
|
|||||||
@@ -476,6 +476,12 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("localDelegatedVal.kt")
|
||||||
|
public void testLocalDelegatedVal() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localDelegatedVal.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("localFunction.kt")
|
@TestMetadata("localFunction.kt")
|
||||||
public void testLocalFunction() throws Exception {
|
public void testLocalFunction() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localFunction.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localFunction.kt");
|
||||||
|
|||||||
@@ -19641,6 +19641,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/script/SimpleScript.kts");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/script/SimpleScript.kts");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("topLevelVariable.kts")
|
||||||
|
public void testTopLevelVariable() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/script/topLevelVariable.kts");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/diagnostics")
|
@TestMetadata("compiler/testData/codegen/box/diagnostics")
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
public interface PropertyAccessorDescriptor extends FunctionDescriptor {
|
public interface PropertyAccessorDescriptor extends VariableAccessorDescriptor {
|
||||||
boolean isDefault();
|
boolean isDefault();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -23,10 +23,12 @@ import org.jetbrains.kotlin.types.TypeSubstitutor;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface PropertyDescriptor extends VariableDescriptor, CallableMemberDescriptor {
|
public interface PropertyDescriptor extends VariableDescriptorWithAccessors, CallableMemberDescriptor {
|
||||||
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
PropertyGetterDescriptor getGetter();
|
PropertyGetterDescriptor getGetter();
|
||||||
|
|
||||||
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
PropertySetterDescriptor getSetter();
|
PropertySetterDescriptor getSetter();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 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.kotlin.descriptors
|
||||||
|
|
||||||
|
public interface VariableAccessorDescriptor : FunctionDescriptor {
|
||||||
|
val correspondingVariable: VariableDescriptorWithAccessors
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 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.kotlin.descriptors
|
||||||
|
|
||||||
|
public interface VariableDescriptorWithAccessors : VariableDescriptor {
|
||||||
|
public val getter: VariableAccessorDescriptor?
|
||||||
|
public val setter: VariableAccessorDescriptor?
|
||||||
|
}
|
||||||
+6
@@ -132,6 +132,12 @@ public abstract class PropertyAccessorDescriptorImpl extends DeclarationDescript
|
|||||||
this.visibility = visibility;
|
this.visibility = visibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public VariableDescriptorWithAccessors getCorrespondingVariable() {
|
||||||
|
return correspondingProperty;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public PropertyDescriptor getCorrespondingProperty() {
|
public PropertyDescriptor getCorrespondingProperty() {
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// "Create property 'foo'" "true"
|
// "Create property 'foo'" "true"
|
||||||
// ERROR: Local variables are not allowed to have delegates
|
|
||||||
// ERROR: Property must be initialized
|
// ERROR: Property must be initialized
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
|
|||||||
Vendored
-1
@@ -1,7 +1,6 @@
|
|||||||
import kotlin.properties.ReadOnlyProperty
|
import kotlin.properties.ReadOnlyProperty
|
||||||
|
|
||||||
// "Create property 'foo'" "true"
|
// "Create property 'foo'" "true"
|
||||||
// ERROR: Local variables are not allowed to have delegates
|
|
||||||
// ERROR: Property must be initialized
|
// ERROR: Property must be initialized
|
||||||
|
|
||||||
val foo: ReadOnlyProperty<Nothing?, Int>
|
val foo: ReadOnlyProperty<Nothing?, Int>
|
||||||
|
|||||||
Reference in New Issue
Block a user