diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowProcessor.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowProcessor.kt index 1c310aa10ae..775b1cd287d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowProcessor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowProcessor.kt @@ -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 visitAssignment(property, getDeferredValue(null), property) generateInstructions(delegate) + if (property.isLocal) { + generateInitializer(property, createSyntheticValue(property, MagicKind.FAKE_INITIALIZER)); + } if (builder.getBoundValue(delegate) != null) { createSyntheticValue(property, MagicKind.VALUE_CONSUMER, delegate) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/LocalVariableAccessorDescriptor.kt b/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/LocalVariableAccessorDescriptor.kt new file mode 100644 index 00000000000..a8f411693fd --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/LocalVariableAccessorDescriptor.kt @@ -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) ""), + 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) + } +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/LocalVariableDescriptor.java b/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/LocalVariableDescriptor.java index a0e89631db7..90ce9cebe2b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/LocalVariableDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/LocalVariableDescriptor.java @@ -24,16 +24,33 @@ import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.types.KotlinType; 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( @NotNull DeclarationDescriptor containingDeclaration, @NotNull Annotations annotations, @NotNull Name name, @Nullable KotlinType type, boolean mutable, + boolean withAccessors, @NotNull SourceElement 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 @@ -53,4 +70,16 @@ public class LocalVariableDescriptor extends VariableDescriptorWithInitializerIm public Visibility getVisibility() { return Visibilities.LOCAL; } + + @Nullable + @Override + public VariableAccessorDescriptor getGetter() { + return getter; + } + + @Nullable + @Override + public VariableAccessorDescriptor getSetter() { + return setter; + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/SyntheticFieldDescriptor.kt b/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/SyntheticFieldDescriptor.kt index a8e58de213f..19daadf52f9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/SyntheticFieldDescriptor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/SyntheticFieldDescriptor.kt @@ -29,7 +29,7 @@ class SyntheticFieldDescriptor private constructor( accessorDescriptor: PropertyAccessorDescriptor, property: KtProperty ): LocalVariableDescriptor(accessorDescriptor, Annotations.EMPTY, SyntheticFieldDescriptor.NAME, - propertyDescriptor.type, propertyDescriptor.isVar, property.toSourceElement()) { + propertyDescriptor.type, propertyDescriptor.isVar, false, property.toSourceElement()) { constructor(accessorDescriptor: PropertyAccessorDescriptor, property: KtProperty): this(accessorDescriptor.correspondingProperty, accessorDescriptor, property) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 2bb2bdebfdd..eba6d9a6476 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -385,7 +385,7 @@ public interface Errors { DiagnosticFactory0 ABSTRACT_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 ACCESSOR_FOR_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 DELEGATED_PROPERTY_IN_INTERFACE = DiagnosticFactory0.create(ERROR); - DiagnosticFactory0 LOCAL_VARIABLE_WITH_DELEGATE = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 SCRIPT_TOP_LEVEL_LOCAL_VARIABLE_WITH_DELEGATE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index f37d19ef2ca..1e193b6f735 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -214,7 +214,7 @@ public class DefaultErrorMessages { 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(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); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java index 40e296f36b9..8828b88d6b1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java @@ -123,10 +123,10 @@ 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> DELEGATED_PROPERTY_RESOLVED_CALL = Slices.createSimpleSlice(); + WritableSlice DELEGATED_PROPERTY_CALL = Slices.createSimpleSlice(); - WritableSlice> DELEGATED_PROPERTY_PD_RESOLVED_CALL = Slices.createSimpleSlice(); + WritableSlice> DELEGATED_PROPERTY_PD_RESOLVED_CALL = Slices.createSimpleSlice(); WritableSlice> COMPONENT_RESOLVED_CALL = Slices.createSimpleSlice(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java index c2fb64a963d..faf005ff855 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java @@ -696,34 +696,12 @@ public class BodyResolver { @NotNull KtExpression delegateExpression, @NotNull LexicalScope propertyHeaderScope ) { - 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 = 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); + delegatedPropertyResolver.resolvePropertyDelegate(outerDataFlowInfo, + property, + propertyDescriptor, + delegateExpression, + propertyHeaderScope, + trace); } private void resolvePropertyInitializer( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt index 0e8198d44e1..cf28f3db7f8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt @@ -400,6 +400,14 @@ class DeclarationsChecker( exposedChecker.checkProperty(property, propertyDescriptor) checkPropertyTypeParametersAreUsedInReceiverType(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) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.java index 35a11a6400d..66a58c21f17 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.java @@ -85,48 +85,93 @@ public class DelegatedPropertyResolver { 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 public KotlinType getDelegatedPropertyGetMethodReturnType( - @NotNull PropertyDescriptor propertyDescriptor, + @NotNull VariableDescriptorWithAccessors variableDescriptor, @NotNull KtExpression delegateExpression, @NotNull KotlinType delegateType, @NotNull BindingTrace trace, @NotNull LexicalScope delegateFunctionsScope ) { - resolveDelegatedPropertyConventionMethod(propertyDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, true); + resolveDelegatedPropertyConventionMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, true); ResolvedCall 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; } public void resolveDelegatedPropertyGetMethod( - @NotNull PropertyDescriptor propertyDescriptor, + @NotNull VariableDescriptorWithAccessors variableDescriptor, @NotNull KtExpression delegateExpression, @NotNull KotlinType delegateType, @NotNull BindingTrace trace, @NotNull LexicalScope delegateFunctionsScope ) { KotlinType returnType = getDelegatedPropertyGetMethodReturnType( - propertyDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope); - KotlinType propertyType = propertyDescriptor.getType(); + variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope); + 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 */ if (!(propertyType instanceof DeferredType) && returnType != null && !KotlinTypeChecker.DEFAULT.isSubtypeOf(returnType, propertyType)) { - Call call = trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, propertyDescriptor.getGetter()); - assert call != null : "Call should exists for " + propertyDescriptor.getGetter(); + Call call = trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, variableDescriptor.getGetter()); + assert call != null : "Call should exists for " + variableDescriptor.getGetter(); 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( - @NotNull PropertyDescriptor propertyDescriptor, + @NotNull VariableDescriptorWithAccessors variableDescriptor, @NotNull KtExpression delegateExpression, @NotNull KotlinType delegateType, @NotNull BindingTrace trace, @NotNull LexicalScope delegateFunctionsScope ) { - resolveDelegatedPropertyConventionMethod(propertyDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, false); + resolveDelegatedPropertyConventionMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, false); } @NotNull @@ -135,7 +180,7 @@ public class DelegatedPropertyResolver { } public void resolveDelegatedPropertyPDMethod( - @NotNull PropertyDescriptor propertyDescriptor, + @NotNull VariableDescriptorWithAccessors variableDescriptor, @NotNull KtExpression delegateExpression, @NotNull KotlinType delegateType, @NotNull BindingTrace trace, @@ -168,19 +213,19 @@ public class DelegatedPropertyResolver { 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 */ private void resolveDelegatedPropertyConventionMethod( - @NotNull PropertyDescriptor propertyDescriptor, + @NotNull VariableDescriptorWithAccessors propertyDescriptor, @NotNull KtExpression delegateExpression, @NotNull KotlinType delegateType, @NotNull BindingTrace trace, @NotNull LexicalScope delegateFunctionsScope, 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(); if (trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, accessor) != null) return; @@ -229,7 +274,7 @@ public class DelegatedPropertyResolver { /* Resolve getValue() or setValue() methods from delegate */ public OverloadResolutionResults getDelegatedPropertyConventionMethod( - @NotNull PropertyDescriptor propertyDescriptor, + @NotNull VariableDescriptorWithAccessors propertyDescriptor, @NotNull KtExpression delegateExpression, @NotNull KotlinType delegateType, @NotNull BindingTrace trace, @@ -237,7 +282,7 @@ public class DelegatedPropertyResolver { boolean isGet, 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(); KotlinType expectedType = isComplete && isGet && !(propertyDescriptor.getType() instanceof DeferredType) @@ -326,7 +371,7 @@ public class DelegatedPropertyResolver { public KotlinType resolveDelegateExpression( @NotNull KtExpression delegateExpression, @NotNull KtProperty property, - @NotNull PropertyDescriptor propertyDescriptor, + @NotNull VariableDescriptorWithAccessors variableDescriptor, @NotNull LexicalScope scopeForDelegate, @NotNull BindingTrace trace, @NotNull DataFlowInfo dataFlowInfo @@ -334,7 +379,7 @@ public class DelegatedPropertyResolver { TemporaryBindingTrace traceToResolveDelegatedProperty = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property"); KtExpression calleeExpression = CallUtilKt.getCalleeExpressionIfAny(delegateExpression); ConstraintSystemCompleter completer = createConstraintSystemCompleter( - property, propertyDescriptor, delegateExpression, scopeForDelegate, trace); + property, variableDescriptor, delegateExpression, scopeForDelegate, trace); if (calleeExpression != null) { traceToResolveDelegatedProperty.record(CONSTRAINT_SYSTEM_COMPLETER, calleeExpression, completer); } @@ -352,13 +397,13 @@ public class DelegatedPropertyResolver { @NotNull private ConstraintSystemCompleter createConstraintSystemCompleter( @NotNull KtProperty property, - @NotNull final PropertyDescriptor propertyDescriptor, + @NotNull final VariableDescriptorWithAccessors variableDescriptor, @NotNull final KtExpression delegateExpression, @NotNull LexicalScope scopeForDelegate, @NotNull final BindingTrace trace ) { - final LexicalScope delegateFunctionsScope = ScopeUtils.makeScopeForDelegateConventionFunctions(scopeForDelegate, propertyDescriptor); - final KotlinType expectedType = property.getTypeReference() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE; + final LexicalScope delegateFunctionsScope = ScopeUtils.makeScopeForDelegateConventionFunctions(scopeForDelegate, variableDescriptor); + final KotlinType expectedType = property.getTypeReference() != null ? variableDescriptor.getType() : NO_EXPECTED_TYPE; return new ConstraintSystemCompleter() { @Override public void completeConstraintSystem( @@ -375,7 +420,7 @@ public class DelegatedPropertyResolver { TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods"); OverloadResolutionResults getMethodResults = getDelegatedPropertyConventionMethod( - propertyDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, delegateFunctionsScope, + variableDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, delegateFunctionsScope, true, false ); @@ -390,16 +435,16 @@ public class DelegatedPropertyResolver { } addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, descriptor); } - if (!propertyDescriptor.isVar()) return; + if (!variableDescriptor.isVar()) return; // 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'. // 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 setMethodResults = getDelegatedPropertyConventionMethod( - propertyDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, delegateFunctionsScope, + variableDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, delegateFunctionsScope, false, false ); @@ -432,8 +477,8 @@ public class DelegatedPropertyResolver { TypeSubstitutor typeVariableSubstitutor, FunctionDescriptor resultingDescriptor ) { - ReceiverParameterDescriptor extensionReceiver = propertyDescriptor.getExtensionReceiverParameter(); - ReceiverParameterDescriptor dispatchReceiver = propertyDescriptor.getDispatchReceiverParameter(); + ReceiverParameterDescriptor extensionReceiver = variableDescriptor.getExtensionReceiverParameter(); + ReceiverParameterDescriptor dispatchReceiver = variableDescriptor.getDispatchReceiverParameter(); KotlinType typeOfThis = extensionReceiver != null ? extensionReceiver.getType() : dispatchReceiver != null ? dispatchReceiver.getType() : diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index 02018afa188..e752831c26c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -655,6 +655,7 @@ public class DescriptorResolver { KtPsiUtil.safeName(parameter.getName()), type, false, + false, KotlinSourceElementKt.toSourceElement(parameter) ); trace.record(BindingContext.VALUE_PARAMETER, parameter, variableDescriptor); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/LocalVariableResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/LocalVariableResolver.kt index e0e814434ee..00c78995ff6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/LocalVariableResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/LocalVariableResolver.kt @@ -35,12 +35,12 @@ import org.jetbrains.kotlin.types.expressions.* import org.jetbrains.kotlin.types.expressions.typeInfoFactory.noTypeInfo class LocalVariableResolver( - private val expressionTypingServices: ExpressionTypingServices, private val modifiersChecker: ModifiersChecker, private val identifierChecker: IdentifierChecker, private val dataFlowAnalyzer: DataFlowAnalyzer, private val annotationResolver: AnnotationResolver, - private val variableTypeResolver: VariableTypeResolver + private val variableTypeResolver: VariableTypeResolver, + private val delegatedPropertyResolver: DelegatedPropertyResolver ) { fun process( @@ -65,13 +65,18 @@ class LocalVariableResolver( context.trace.report(LOCAL_VARIABLE_WITH_SETTER.on(setter)) } + val propertyDescriptor = resolveLocalVariableDescriptor(scope, property, context.dataFlowInfo, context.trace) + val delegateExpression = property.delegateExpression - if (delegateExpression != null) { - expressionTypingServices.getTypeInfo(delegateExpression, context) - context.trace.report(LOCAL_VARIABLE_WITH_DELEGATE.on(property.delegate!!)) + if (delegateExpression != null && propertyDescriptor is VariableDescriptorWithAccessors) { + delegatedPropertyResolver.resolvePropertyDelegate(typingContext.dataFlowInfo, + property, + propertyDescriptor, + delegateExpression, + typingContext.scope, + typingContext.trace); } - val propertyDescriptor = resolveLocalVariableDescriptor(scope, property, context.dataFlowInfo, context.trace) val initializer = property.initializer var typeInfo: KotlinTypeInfo if (initializer != null) { @@ -167,12 +172,14 @@ class LocalVariableResolver( type: KotlinType?, trace: BindingTrace ): LocalVariableDescriptor { + val hasDelegate = variable is KtProperty && variable.hasDelegate(); val variableDescriptor = LocalVariableDescriptor( scope.ownerDescriptor, annotationResolver.resolveAnnotationsWithArguments(scope, variable.modifierList, trace), KtPsiUtil.safeName(variable.name), type, variable.isVar, + hasDelegate, variable.toSourceElement() ) trace.record(BindingContext.VARIABLE, variable, variableDescriptor) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt index d10900f6502..873a72ba9bb 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt @@ -202,7 +202,7 @@ private fun bindFunctionReference(expression: KtCallableReferenceExpression, typ private fun bindPropertyReference(expression: KtCallableReferenceExpression, referenceType: KotlinType, context: ResolutionContext<*>) { val localVariable = LocalVariableDescriptor(context.scope.ownerDescriptor, Annotations.EMPTY, Name.special(""), - referenceType, /* mutable = */ false, expression.toSourceElement()) + referenceType, /* mutable = */ false, false, expression.toSourceElement()) context.trace.record(BindingContext.VARIABLE, expression, localVariable) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java index 6d2746f4348..5cb2eb7f76f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java @@ -60,7 +60,7 @@ public class ExpressionTypingComponents { /*package*/ DeclarationsCheckerBuilder declarationsCheckerBuilder; /*package*/ LocalVariableResolver localVariableResolver; /*package*/ LookupTracker lookupTracker; - + /*package*/ DelegatedPropertyResolver delegatedPropertyResolver; @Inject public void setGlobalContext(@NotNull GlobalContext globalContext) { @@ -201,4 +201,9 @@ public class ExpressionTypingComponents { public void setLookupTracker(@NotNull LookupTracker lookupTracker) { this.lookupTracker = lookupTracker; } + + @Inject + public void setDelegatedPropertyResolver(DelegatedPropertyResolver delegatedPropertyResolver) { + this.delegatedPropertyResolver = delegatedPropertyResolver; + } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/ScopeUtils.java b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/ScopeUtils.java index ea880f7fce5..fec11df4d66 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/ScopeUtils.java +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/ScopeUtils.java @@ -20,10 +20,7 @@ import kotlin.Unit; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.descriptors.ClassDescriptor; -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; -import org.jetbrains.kotlin.descriptors.PropertyDescriptor; -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; +import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.utils.Printer; public final class ScopeUtils { @@ -69,10 +66,10 @@ public final class ScopeUtils { @NotNull public static LexicalScope makeScopeForDelegateConventionFunctions( @NotNull LexicalScope parent, - @NotNull PropertyDescriptor propertyDescriptor + @NotNull VariableDescriptorWithAccessors variableDescriptor ) { // todo: very strange scope! - return new LexicalScopeImpl(parent, propertyDescriptor, true, propertyDescriptor.getExtensionReceiverParameter(), + return new LexicalScopeImpl(parent, variableDescriptor, true, variableDescriptor.getExtensionReceiverParameter(), LexicalScopeKind.PROPERTY_DELEGATE_METHOD ); } diff --git a/compiler/testData/cfg/declarations/local/localDelegatedVal.instructions b/compiler/testData/cfg/declarations/local/localDelegatedVal.instructions new file mode 100644 index 00000000000..29e71565580 --- /dev/null +++ b/compiler/testData/cfg/declarations/local/localDelegatedVal.instructions @@ -0,0 +1,60 @@ +== Delegate == +class Delegate { + operator fun getValue(t: Any?, p: KProperty<*>): Int = 1 +} +--------------------- +L0: + 1 +L1: + NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== getValue == +operator fun getValue(t: Any?, p: KProperty<*>): Int = 1 +--------------------- +L0: + 1 + v(t: Any?) + magic[FAKE_INITIALIZER](t: Any?) -> + w(t|) + v(p: KProperty<*>) + magic[FAKE_INITIALIZER](p: KProperty<*>) -> + w(p|) + r(1) -> + ret(*|) L1 +L1: + NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== foo == +fun foo(): Int { + val prop: Int by Delegate() + return prop +} +--------------------- +L0: + 1 + 2 mark({ val prop: Int by Delegate() return prop }) + v(val prop: Int by Delegate()) + magic[UNRECOGNIZED_WRITE_RHS](val prop: Int by Delegate()) -> + w(prop|) + mark(Delegate()) + call(Delegate(), ) -> + magic[FAKE_INITIALIZER](val prop: Int by Delegate()) -> + w(prop|) + magic[VALUE_CONSUMER](val prop: Int by Delegate()|) -> + r(prop) -> + ret(*|) L1 +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== diff --git a/compiler/testData/cfg/declarations/local/localDelegatedVal.kt b/compiler/testData/cfg/declarations/local/localDelegatedVal.kt new file mode 100644 index 00000000000..ef3840e29f8 --- /dev/null +++ b/compiler/testData/cfg/declarations/local/localDelegatedVal.kt @@ -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 +} diff --git a/compiler/testData/cfg/declarations/local/localDelegatedVal.values b/compiler/testData/cfg/declarations/local/localDelegatedVal.values new file mode 100644 index 00000000000..c6c8f25a02b --- /dev/null +++ b/compiler/testData/cfg/declarations/local/localDelegatedVal.values @@ -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 +--------------------- + : * NEW: magic[FAKE_INITIALIZER](t: Any?) -> + : {<: KProperty<*>} NEW: magic[FAKE_INITIALIZER](p: KProperty<*>) -> +1 : Int NEW: r(1) -> +===================== +== foo == +fun foo(): Int { + val prop: Int by Delegate() + return prop +} +--------------------- + : Int NEW: magic[UNRECOGNIZED_WRITE_RHS](val prop: Int by Delegate()) -> + : Int NEW: magic[FAKE_INITIALIZER](val prop: Int by Delegate()) -> + : * NEW: magic[VALUE_CONSUMER](val prop: Int by Delegate()|) -> +Delegate() : * NEW: call(Delegate(), ) -> +prop : Int NEW: r(prop) -> +return prop !: * +{ val prop: Int by Delegate() return prop } !: * COPY +===================== diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/localVariable.kt b/compiler/testData/diagnostics/tests/delegatedProperty/localVariable.kt index a0564e060f1..4816a3d23d4 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/localVariable.kt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/localVariable.kt @@ -3,13 +3,13 @@ import kotlin.reflect.KProperty class Local { - fun foo() { - val a: Int by Delegate() - } + fun foo() { + val a: Int by Delegate() + } } class Delegate { - fun getValue(t: Any?, p: KProperty<*>): Int { - return 1 - } + operator fun getValue(t: Any?, p: KProperty<*>): Int { + return 1 + } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/localVariable.txt b/compiler/testData/diagnostics/tests/delegatedProperty/localVariable.txt index c0d4b6ba5c8..631b90f6480 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/localVariable.txt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/localVariable.txt @@ -3,7 +3,7 @@ package public final class Delegate { public constructor Delegate() 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 toString(): kotlin.String } diff --git a/compiler/testData/diagnostics/tests/script/topLevelVariable.kts b/compiler/testData/diagnostics/tests/script/topLevelVariable.kts new file mode 100644 index 00000000000..556786af7ed --- /dev/null +++ b/compiler/testData/diagnostics/tests/script/topLevelVariable.kts @@ -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 by Delegate() + +class Foo { + val a: Int by Delegate() +} + +fun foo() { + val a: Int by Delegate() +} + diff --git a/compiler/testData/diagnostics/tests/script/topLevelVariable.txt b/compiler/testData/diagnostics/tests/script/topLevelVariable.txt new file mode 100644 index 00000000000..ca792f0046a --- /dev/null +++ b/compiler/testData/diagnostics/tests/script/topLevelVariable.txt @@ -0,0 +1,27 @@ +package + +public final class TopLevelVariable { + public constructor TopLevelVariable(/*0*/ args: kotlin.Array) + public final val a: kotlin.Int + public final val args: kotlin.Array + 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 + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java index d8d55217ba5..d6a22af62f7 100644 --- a/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java @@ -474,6 +474,12 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest { 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") public void testLocalFunction() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localFunction.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java index 0133af47937..6f20b22ce6d 100644 --- a/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java @@ -476,6 +476,12 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest { 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") public void testLocalFunction() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localFunction.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 41fe6baad18..9bbd963111a 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -19641,6 +19641,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/script/SimpleScript.kts"); 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") diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyAccessorDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyAccessorDescriptor.java index ce40675b707..4e5906306ac 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyAccessorDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyAccessorDescriptor.java @@ -20,7 +20,7 @@ import org.jetbrains.annotations.NotNull; import java.util.Collection; -public interface PropertyAccessorDescriptor extends FunctionDescriptor { +public interface PropertyAccessorDescriptor extends VariableAccessorDescriptor { boolean isDefault(); @NotNull diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyDescriptor.java index de12acc7630..1162bfa6e5e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/PropertyDescriptor.java @@ -23,10 +23,12 @@ import org.jetbrains.kotlin.types.TypeSubstitutor; import java.util.Collection; import java.util.List; -public interface PropertyDescriptor extends VariableDescriptor, CallableMemberDescriptor { +public interface PropertyDescriptor extends VariableDescriptorWithAccessors, CallableMemberDescriptor { + @Override @Nullable PropertyGetterDescriptor getGetter(); + @Override @Nullable PropertySetterDescriptor getSetter(); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/VariableAccessorDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/VariableAccessorDescriptor.kt new file mode 100644 index 00000000000..d91c7a92668 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/VariableAccessorDescriptor.kt @@ -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 +} \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/VariableDescriptorWithAccessors.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/VariableDescriptorWithAccessors.kt new file mode 100644 index 00000000000..a26b4bc01b0 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/VariableDescriptorWithAccessors.kt @@ -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? +} \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyAccessorDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyAccessorDescriptorImpl.java index a64c40156cb..2c8c945ee07 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyAccessorDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyAccessorDescriptorImpl.java @@ -132,6 +132,12 @@ public abstract class PropertyAccessorDescriptorImpl extends DeclarationDescript this.visibility = visibility; } + @NotNull + @Override + public VariableDescriptorWithAccessors getCorrespondingVariable() { + return correspondingProperty; + } + @Override @NotNull public PropertyDescriptor getCorrespondingProperty() { diff --git a/idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt b/idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt index 85550c300d1..e8c2b7be978 100644 --- a/idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt +++ b/idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt @@ -1,5 +1,4 @@ // "Create property 'foo'" "true" -// ERROR: Local variables are not allowed to have delegates // ERROR: Property must be initialized fun test() { diff --git a/idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt.after b/idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt.after index 394e5ba90e7..96b0cdae1e9 100644 --- a/idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt.after +++ b/idea/testData/quickfix/createFromUsage/createVariable/property/localValDelegateRuntime.kt.after @@ -1,7 +1,6 @@ import kotlin.properties.ReadOnlyProperty // "Create property 'foo'" "true" -// ERROR: Local variables are not allowed to have delegates // ERROR: Property must be initialized val foo: ReadOnlyProperty