'createDelegate' operator convention:
- resolution & inference - additional diagnostic for language feature support
This commit is contained in:
committed by
Stanislav Erokhin
parent
d3ab0f066e
commit
e2ba288323
@@ -141,6 +141,8 @@ public interface BindingContext {
|
|||||||
|
|
||||||
WritableSlice<VariableAccessorDescriptor, ResolvedCall<FunctionDescriptor>> DELEGATED_PROPERTY_RESOLVED_CALL = Slices.createSimpleSlice();
|
WritableSlice<VariableAccessorDescriptor, ResolvedCall<FunctionDescriptor>> DELEGATED_PROPERTY_RESOLVED_CALL = Slices.createSimpleSlice();
|
||||||
WritableSlice<VariableAccessorDescriptor, Call> DELEGATED_PROPERTY_CALL = Slices.createSimpleSlice();
|
WritableSlice<VariableAccessorDescriptor, Call> DELEGATED_PROPERTY_CALL = Slices.createSimpleSlice();
|
||||||
|
WritableSlice<VariableDescriptorWithAccessors, ResolvedCall<FunctionDescriptor>> CREATE_DELEGATE_RESOLVED_CALL = Slices.createSimpleSlice();
|
||||||
|
WritableSlice<VariableDescriptorWithAccessors, Call> CREATE_DELEGATE_CALL = Slices.createSimpleSlice();
|
||||||
|
|
||||||
WritableSlice<VariableDescriptorWithAccessors, ResolvedCall<FunctionDescriptor>> DELEGATED_PROPERTY_PD_RESOLVED_CALL = Slices.createSimpleSlice();
|
WritableSlice<VariableDescriptorWithAccessors, ResolvedCall<FunctionDescriptor>> DELEGATED_PROPERTY_PD_RESOLVED_CALL = Slices.createSimpleSlice();
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.resolve
|
|||||||
|
|
||||||
import com.google.common.collect.Lists
|
import com.google.common.collect.Lists
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
|
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
|
||||||
@@ -51,7 +53,8 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
|
|||||||
class DelegatedPropertyResolver(
|
class DelegatedPropertyResolver(
|
||||||
private val builtIns: KotlinBuiltIns,
|
private val builtIns: KotlinBuiltIns,
|
||||||
private val fakeCallResolver: FakeCallResolver,
|
private val fakeCallResolver: FakeCallResolver,
|
||||||
private val expressionTypingServices: ExpressionTypingServices
|
private val expressionTypingServices: ExpressionTypingServices,
|
||||||
|
private val languageVersionSettings: LanguageVersionSettings
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun resolvePropertyDelegate(
|
fun resolvePropertyDelegate(
|
||||||
@@ -81,31 +84,53 @@ class DelegatedPropertyResolver(
|
|||||||
delegateFunctionsScope = initializerScope
|
delegateFunctionsScope = initializerScope
|
||||||
}
|
}
|
||||||
|
|
||||||
val delegateType = resolveDelegateExpression(delegateExpression, property, variableDescriptor, initializerScope, trace, outerDataFlowInfo)
|
val byExpressionType = resolveDelegateExpression(delegateExpression, property, variableDescriptor, initializerScope, trace, outerDataFlowInfo)
|
||||||
resolveDelegatedPropertyGetMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, outerDataFlowInfo)
|
|
||||||
|
resolveCreateDelegateMethod(variableDescriptor, delegateExpression, byExpressionType, trace, delegateFunctionsScope, outerDataFlowInfo)
|
||||||
|
val delegateType = getResolvedDelegateType(variableDescriptor, delegateExpression, byExpressionType, trace)
|
||||||
|
|
||||||
|
resolveGetValueMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, outerDataFlowInfo)
|
||||||
if (property.isVar) {
|
if (property.isVar) {
|
||||||
resolveDelegatedPropertySetMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, outerDataFlowInfo)
|
resolveSetValueMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, outerDataFlowInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveDelegatedPropertyPDMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, outerDataFlowInfo)
|
resolvePropertyDelegatedMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, outerDataFlowInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDelegatedPropertyGetMethodReturnType(
|
private fun getResolvedDelegateType(
|
||||||
variableDescriptor: VariableDescriptorWithAccessors,
|
variableDescriptor: VariableDescriptorWithAccessors,
|
||||||
delegateExpression: KtExpression,
|
delegateExpression: KtExpression,
|
||||||
delegateType: KotlinType,
|
byExpressionType: KotlinType,
|
||||||
|
trace: BindingTrace
|
||||||
|
): KotlinType {
|
||||||
|
val createDelegateResolvedCall = trace.bindingContext.get(CREATE_DELEGATE_RESOLVED_CALL, variableDescriptor)
|
||||||
|
if (createDelegateResolvedCall != null) {
|
||||||
|
return createDelegateResolvedCall.resultingDescriptor.returnType
|
||||||
|
?: throw AssertionError("No return type fore 'createDelegate' of ${delegateExpression.text}")
|
||||||
|
}
|
||||||
|
return byExpressionType
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getGetValueMethodReturnType(
|
||||||
|
variableDescriptor: VariableDescriptorWithAccessors,
|
||||||
|
delegateExpression: KtExpression,
|
||||||
|
byExpressionType: KotlinType,
|
||||||
trace: BindingTrace,
|
trace: BindingTrace,
|
||||||
delegateFunctionsScope: LexicalScope,
|
delegateFunctionsScope: LexicalScope,
|
||||||
dataFlowInfo: DataFlowInfo
|
dataFlowInfo: DataFlowInfo
|
||||||
): KotlinType? {
|
): KotlinType? {
|
||||||
resolveDelegatedPropertyConventionMethod(
|
resolveCreateDelegateMethod(variableDescriptor, delegateExpression, byExpressionType, trace, delegateFunctionsScope, dataFlowInfo)
|
||||||
variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, dataFlowInfo, true
|
val delegateType = getResolvedDelegateType(variableDescriptor, delegateExpression, byExpressionType, trace)
|
||||||
)
|
resolveGetSetValueMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, dataFlowInfo, true)
|
||||||
|
|
||||||
val resolvedCall = trace.bindingContext.get(DELEGATED_PROPERTY_RESOLVED_CALL, variableDescriptor.getter)
|
val resolvedCall = trace.bindingContext.get(DELEGATED_PROPERTY_RESOLVED_CALL, variableDescriptor.getter)
|
||||||
return if (resolvedCall != null) resolvedCall.resultingDescriptor.returnType else null
|
return if (resolvedCall != null) resolvedCall.resultingDescriptor.returnType else null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveDelegatedPropertyGetMethod(
|
private val isOperatorCreateDelegateSupported: Boolean
|
||||||
|
get() = languageVersionSettings.supportsFeature(LanguageFeature.OperatorCreateDelegate)
|
||||||
|
|
||||||
|
private fun resolveGetValueMethod(
|
||||||
variableDescriptor: VariableDescriptorWithAccessors,
|
variableDescriptor: VariableDescriptorWithAccessors,
|
||||||
delegateExpression: KtExpression,
|
delegateExpression: KtExpression,
|
||||||
delegateType: KotlinType,
|
delegateType: KotlinType,
|
||||||
@@ -113,9 +138,7 @@ class DelegatedPropertyResolver(
|
|||||||
delegateFunctionsScope: LexicalScope,
|
delegateFunctionsScope: LexicalScope,
|
||||||
dataFlowInfo: DataFlowInfo
|
dataFlowInfo: DataFlowInfo
|
||||||
) {
|
) {
|
||||||
val returnType = getDelegatedPropertyGetMethodReturnType(
|
val returnType = getGetValueMethodReturnType(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, dataFlowInfo)
|
||||||
variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, dataFlowInfo
|
|
||||||
)
|
|
||||||
val propertyType = variableDescriptor.type
|
val propertyType = variableDescriptor.type
|
||||||
|
|
||||||
/* 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 */
|
||||||
@@ -127,7 +150,7 @@ class DelegatedPropertyResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveDelegatedPropertySetMethod(
|
private fun resolveSetValueMethod(
|
||||||
variableDescriptor: VariableDescriptorWithAccessors,
|
variableDescriptor: VariableDescriptorWithAccessors,
|
||||||
delegateExpression: KtExpression,
|
delegateExpression: KtExpression,
|
||||||
delegateType: KotlinType,
|
delegateType: KotlinType,
|
||||||
@@ -135,15 +158,15 @@ class DelegatedPropertyResolver(
|
|||||||
delegateFunctionsScope: LexicalScope,
|
delegateFunctionsScope: LexicalScope,
|
||||||
dataFlowInfo: DataFlowInfo
|
dataFlowInfo: DataFlowInfo
|
||||||
) {
|
) {
|
||||||
resolveDelegatedPropertyConventionMethod(variableDescriptor, delegateExpression, delegateType, trace,
|
resolveGetSetValueMethod(variableDescriptor, delegateExpression, delegateType, trace,
|
||||||
delegateFunctionsScope, dataFlowInfo, false)
|
delegateFunctionsScope, dataFlowInfo, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createExpressionForProperty(psiFactory: KtPsiFactory): KtExpression {
|
private fun KtPsiFactory.createExpressionForProperty(): KtExpression {
|
||||||
return psiFactory.createExpression("null as ${KotlinBuiltIns.FQ_NAMES.kProperty.asSingleFqName().asString()}<*>")
|
return createExpression("null as ${KotlinBuiltIns.FQ_NAMES.kProperty.asSingleFqName().asString()}<*>")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveDelegatedPropertyPDMethod(
|
private fun resolvePropertyDelegatedMethod(
|
||||||
variableDescriptor: VariableDescriptorWithAccessors,
|
variableDescriptor: VariableDescriptorWithAccessors,
|
||||||
delegateExpression: KtExpression,
|
delegateExpression: KtExpression,
|
||||||
delegateType: KotlinType,
|
delegateType: KotlinType,
|
||||||
@@ -155,7 +178,7 @@ class DelegatedPropertyResolver(
|
|||||||
val context = ExpressionTypingContext.newContext(traceToResolvePDMethod, delegateFunctionsScope, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE)
|
val context = ExpressionTypingContext.newContext(traceToResolvePDMethod, delegateFunctionsScope, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE)
|
||||||
|
|
||||||
val psiFactory = KtPsiFactory(delegateExpression)
|
val psiFactory = KtPsiFactory(delegateExpression)
|
||||||
val arguments = listOf(createExpressionForProperty(psiFactory))
|
val arguments = listOf(psiFactory.createExpressionForProperty())
|
||||||
val receiver = ExpressionReceiver.create(delegateExpression, delegateType, trace.bindingContext)
|
val receiver = ExpressionReceiver.create(delegateExpression, delegateType, trace.bindingContext)
|
||||||
|
|
||||||
val resolutionResult = fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments,
|
val resolutionResult = fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments,
|
||||||
@@ -180,7 +203,7 @@ class DelegatedPropertyResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Resolve getValue() or setValue() methods from delegate */
|
/* Resolve getValue() or setValue() methods from delegate */
|
||||||
private fun resolveDelegatedPropertyConventionMethod(
|
private fun resolveGetSetValueMethod(
|
||||||
propertyDescriptor: VariableDescriptorWithAccessors,
|
propertyDescriptor: VariableDescriptorWithAccessors,
|
||||||
delegateExpression: KtExpression,
|
delegateExpression: KtExpression,
|
||||||
delegateType: KotlinType,
|
delegateType: KotlinType,
|
||||||
@@ -194,34 +217,26 @@ class DelegatedPropertyResolver(
|
|||||||
|
|
||||||
if (trace.bindingContext.get(DELEGATED_PROPERTY_CALL, accessor) != null) return
|
if (trace.bindingContext.get(DELEGATED_PROPERTY_CALL, accessor) != null) return
|
||||||
|
|
||||||
val functionResults = getDelegatedPropertyConventionMethod(propertyDescriptor, delegateExpression, delegateType, trace,
|
val functionResults = getGetSetValueMethod(
|
||||||
delegateFunctionsScope, dataFlowInfo, isGet, true)
|
propertyDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, dataFlowInfo,
|
||||||
val call = trace.bindingContext.get(DELEGATED_PROPERTY_CALL, accessor)
|
isGet = isGet, isComplete = true
|
||||||
?: throw AssertionError("'getDelegatedPropertyConventionMethod' didn't record a call")
|
)
|
||||||
|
|
||||||
if (!functionResults.isSuccess) {
|
if (!functionResults.isSuccess) {
|
||||||
val expectedFunction = renderCall(call, trace.bindingContext)
|
val call = trace.bindingContext.get(DELEGATED_PROPERTY_CALL, accessor)
|
||||||
when {
|
?: throw AssertionError("'getDelegatedPropertyConventionMethod' didn't record a call")
|
||||||
functionResults.isSingleResult ||
|
reportDelegateOperatorResolutionError(trace, call, functionResults, delegateExpression, delegateType)
|
||||||
functionResults.isIncomplete ||
|
|
||||||
functionResults.resultCode == OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES ->
|
|
||||||
trace.report(DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE.on(delegateExpression, expectedFunction, functionResults.resultingCalls))
|
|
||||||
functionResults.isAmbiguity ->
|
|
||||||
trace.report(DELEGATE_SPECIAL_FUNCTION_AMBIGUITY.on(delegateExpression, expectedFunction, functionResults.resultingCalls))
|
|
||||||
else ->
|
|
||||||
trace.report(DELEGATE_SPECIAL_FUNCTION_MISSING.on(delegateExpression, expectedFunction, delegateType))
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val resultingDescriptor = functionResults.resultingDescriptor
|
val resultingDescriptor = functionResults.resultingDescriptor
|
||||||
|
|
||||||
val resultingCall = functionResults.resultingCall
|
val resultingCall = functionResults.resultingCall
|
||||||
val declaration = DescriptorToSourceUtils.descriptorToDeclaration(propertyDescriptor)
|
|
||||||
if (declaration is KtProperty) {
|
if (!resultingDescriptor.isOperator) {
|
||||||
val delegate = declaration.delegate
|
val declaration = DescriptorToSourceUtils.descriptorToDeclaration(propertyDescriptor)
|
||||||
if (delegate != null) {
|
if (declaration is KtProperty) {
|
||||||
if (!resultingDescriptor.isOperator) {
|
val delegate = declaration.delegate
|
||||||
|
if (delegate != null) {
|
||||||
val byKeyword = delegate.byKeywordNode.psi
|
val byKeyword = delegate.byKeywordNode.psi
|
||||||
OperatorCallChecker.report(byKeyword, resultingDescriptor, trace)
|
OperatorCallChecker.report(byKeyword, resultingDescriptor, trace)
|
||||||
}
|
}
|
||||||
@@ -231,8 +246,61 @@ class DelegatedPropertyResolver(
|
|||||||
trace.record(DELEGATED_PROPERTY_RESOLVED_CALL, accessor, resultingCall)
|
trace.record(DELEGATED_PROPERTY_RESOLVED_CALL, accessor, resultingCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun reportDelegateOperatorResolutionError(
|
||||||
|
trace: BindingTrace,
|
||||||
|
delegateOperatorCall: Call,
|
||||||
|
delegateOperatorResults: OverloadResolutionResults<FunctionDescriptor>,
|
||||||
|
delegateExpression: KtExpression,
|
||||||
|
delegateType: KotlinType,
|
||||||
|
operatorRequired: Boolean = true
|
||||||
|
) {
|
||||||
|
val expectedFunction = renderCall(delegateOperatorCall, trace.bindingContext)
|
||||||
|
|
||||||
|
when {
|
||||||
|
delegateOperatorResults.isSingleResult ||
|
||||||
|
delegateOperatorResults.isIncomplete ||
|
||||||
|
delegateOperatorResults.resultCode == OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES ->
|
||||||
|
trace.report(DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE.on(delegateExpression, expectedFunction, delegateOperatorResults.resultingCalls))
|
||||||
|
delegateOperatorResults.isAmbiguity ->
|
||||||
|
trace.report(DELEGATE_SPECIAL_FUNCTION_AMBIGUITY.on(delegateExpression, expectedFunction, delegateOperatorResults.resultingCalls))
|
||||||
|
else ->
|
||||||
|
if (operatorRequired) trace.report(DELEGATE_SPECIAL_FUNCTION_MISSING.on(delegateExpression, expectedFunction, delegateType))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resolveCreateDelegateMethod(
|
||||||
|
propertyDescriptor: VariableDescriptorWithAccessors,
|
||||||
|
byExpression: KtExpression,
|
||||||
|
byExpressionType: KotlinType,
|
||||||
|
trace: BindingTrace,
|
||||||
|
delegateFunctionsScope: LexicalScope,
|
||||||
|
dataFlowInfo: DataFlowInfo
|
||||||
|
) {
|
||||||
|
if (!isOperatorCreateDelegateSupported) return
|
||||||
|
if (trace.bindingContext.get(BindingContext.CREATE_DELEGATE_CALL, propertyDescriptor) != null) return
|
||||||
|
|
||||||
|
val createDelegateResults = getCreateDelegateMethod(propertyDescriptor, byExpression, byExpressionType,
|
||||||
|
trace, delegateFunctionsScope, dataFlowInfo)
|
||||||
|
if (!createDelegateResults.isSuccess) {
|
||||||
|
val call = trace.bindingContext.get(BindingContext.CREATE_DELEGATE_CALL, propertyDescriptor)
|
||||||
|
?: throw AssertionError("'getDelegatedPropertyConventionMethod' didn't record a call")
|
||||||
|
reportDelegateOperatorResolutionError(trace, call, createDelegateResults, byExpression, byExpressionType,
|
||||||
|
operatorRequired = false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val resultingDescriptor = createDelegateResults.resultingDescriptor
|
||||||
|
if (!resultingDescriptor.isOperator) {
|
||||||
|
// TODO resolved 'createDelegate' function, which is not an operator - warning?
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val resultingCall = createDelegateResults.resultingCall
|
||||||
|
trace.record(CREATE_DELEGATE_RESOLVED_CALL, propertyDescriptor, resultingCall)
|
||||||
|
}
|
||||||
|
|
||||||
/* Resolve getValue() or setValue() methods from delegate */
|
/* Resolve getValue() or setValue() methods from delegate */
|
||||||
private fun getDelegatedPropertyConventionMethod(
|
private fun getGetSetValueMethod(
|
||||||
propertyDescriptor: VariableDescriptorWithAccessors,
|
propertyDescriptor: VariableDescriptorWithAccessors,
|
||||||
delegateExpression: KtExpression,
|
delegateExpression: KtExpression,
|
||||||
delegateType: KotlinType,
|
delegateType: KotlinType,
|
||||||
@@ -257,7 +325,7 @@ class DelegatedPropertyResolver(
|
|||||||
val arguments = Lists.newArrayList<KtExpression>()
|
val arguments = Lists.newArrayList<KtExpression>()
|
||||||
val psiFactory = KtPsiFactory(delegateExpression)
|
val psiFactory = KtPsiFactory(delegateExpression)
|
||||||
arguments.add(psiFactory.createExpression(if (hasThis) "this" else "null"))
|
arguments.add(psiFactory.createExpression(if (hasThis) "this" else "null"))
|
||||||
arguments.add(createExpressionForProperty(psiFactory))
|
arguments.add(psiFactory.createExpressionForProperty())
|
||||||
|
|
||||||
if (!isGet) {
|
if (!isGet) {
|
||||||
val fakeArgument = createFakeExpressionOfType(delegateExpression.project, trace,
|
val fakeArgument = createFakeExpressionOfType(delegateExpression.project, trace,
|
||||||
@@ -277,6 +345,34 @@ class DelegatedPropertyResolver(
|
|||||||
return resolutionResult.second
|
return resolutionResult.second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getCreateDelegateMethod(
|
||||||
|
propertyDescriptor: VariableDescriptorWithAccessors,
|
||||||
|
delegateExpression: KtExpression,
|
||||||
|
delegateExpressionType: KotlinType,
|
||||||
|
trace: BindingTrace,
|
||||||
|
delegateFunctionsScope: LexicalScope,
|
||||||
|
dataFlowInfo: DataFlowInfo
|
||||||
|
): OverloadResolutionResults<FunctionDescriptor> {
|
||||||
|
val expectedType = TypeUtils.NO_EXPECTED_TYPE
|
||||||
|
val context = ExpressionTypingContext.newContext(trace, delegateFunctionsScope, dataFlowInfo, expectedType)
|
||||||
|
val propertyHasReceiver = propertyDescriptor.extensionReceiverParameter != null ||
|
||||||
|
propertyDescriptor.dispatchReceiverParameter != null
|
||||||
|
val arguments = KtPsiFactory(delegateExpression).run {
|
||||||
|
listOf(
|
||||||
|
createExpression(if (propertyHasReceiver) "this" else "null"),
|
||||||
|
createExpressionForProperty()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val functionName = OperatorNameConventions.CREATE_DELEGATE
|
||||||
|
val receiver = ExpressionReceiver.create(delegateExpression, delegateExpressionType, trace.bindingContext)
|
||||||
|
|
||||||
|
val (createDelegateCall, createDelegateResolutionResult) =
|
||||||
|
fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments, functionName, delegateExpression)
|
||||||
|
trace.record(BindingContext.CREATE_DELEGATE_CALL, propertyDescriptor, createDelegateCall)
|
||||||
|
|
||||||
|
return createDelegateResolutionResult
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: diagnostics rendering does not belong here
|
//TODO: diagnostics rendering does not belong here
|
||||||
private fun renderCall(call: Call, context: BindingContext): String {
|
private fun renderCall(call: Call, context: BindingContext): String {
|
||||||
val calleeExpression = call.calleeExpression
|
val calleeExpression = call.calleeExpression
|
||||||
@@ -303,15 +399,16 @@ class DelegatedPropertyResolver(
|
|||||||
): KotlinType {
|
): KotlinType {
|
||||||
val traceToResolveDelegatedProperty = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property")
|
val traceToResolveDelegatedProperty = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property")
|
||||||
val calleeExpression = delegateExpression.getCalleeExpressionIfAny()
|
val calleeExpression = delegateExpression.getCalleeExpressionIfAny()
|
||||||
val completer = createConstraintSystemCompleter(
|
val completer = createConstraintSystemCompleter(property, variableDescriptor, delegateExpression, scopeForDelegate, trace, dataFlowInfo)
|
||||||
property, variableDescriptor, delegateExpression, scopeForDelegate, trace, dataFlowInfo
|
|
||||||
)
|
calleeExpression?.let {
|
||||||
if (calleeExpression != null) {
|
traceToResolveDelegatedProperty.record(CONSTRAINT_SYSTEM_COMPLETER, it, completer)
|
||||||
traceToResolveDelegatedProperty.record(CONSTRAINT_SYSTEM_COMPLETER, calleeExpression, completer)
|
|
||||||
}
|
}
|
||||||
val delegateType = expressionTypingServices.safeGetType(scopeForDelegate, delegateExpression, NO_EXPECTED_TYPE,
|
|
||||||
dataFlowInfo, traceToResolveDelegatedProperty)
|
val delegateType = expressionTypingServices.safeGetType(scopeForDelegate, delegateExpression, NO_EXPECTED_TYPE, dataFlowInfo, traceToResolveDelegatedProperty)
|
||||||
traceToResolveDelegatedProperty.commit({ slice, key -> slice !== CONSTRAINT_SYSTEM_COMPLETER }, true)
|
|
||||||
|
traceToResolveDelegatedProperty.commit({ slice, _ -> slice !== CONSTRAINT_SYSTEM_COMPLETER }, true)
|
||||||
|
|
||||||
return delegateType
|
return delegateType
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,21 +431,23 @@ class DelegatedPropertyResolver(
|
|||||||
?: throw AssertionError("No substitutor in the system for call: " + resolvedCall.call)
|
?: throw AssertionError("No substitutor in the system for call: " + resolvedCall.call)
|
||||||
|
|
||||||
val traceToResolveConventionMethods = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods")
|
val traceToResolveConventionMethods = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods")
|
||||||
val getMethodResults = getDelegatedPropertyConventionMethod(
|
|
||||||
variableDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, delegateFunctionsScope,
|
|
||||||
dataFlowInfo, true, false
|
|
||||||
)
|
|
||||||
|
|
||||||
if (conventionMethodFound(getMethodResults)) {
|
val delegateType = getDelegateType(returnType, constraintSystem, typeVariableSubstitutor, traceToResolveConventionMethods)
|
||||||
val descriptor = getMethodResults.resultingDescriptor
|
|
||||||
val returnTypeOfGetMethod = descriptor.returnType
|
val getValueResults = getGetSetValueMethod(
|
||||||
if (returnTypeOfGetMethod != null && !TypeUtils.noExpectedType(expectedType)) {
|
variableDescriptor, delegateExpression, delegateType, traceToResolveConventionMethods, delegateFunctionsScope, dataFlowInfo,
|
||||||
val returnTypeInSystem = typeVariableSubstitutor.substitute(returnTypeOfGetMethod, Variance.INVARIANT)
|
isGet = true, isComplete = false
|
||||||
|
)
|
||||||
|
if (conventionMethodFound(getValueResults)) {
|
||||||
|
val getValueDescriptor = getValueResults.resultingDescriptor
|
||||||
|
val getValueReturnType = getValueDescriptor.returnType
|
||||||
|
if (getValueReturnType != null && !TypeUtils.noExpectedType(expectedType)) {
|
||||||
|
val returnTypeInSystem = typeVariableSubstitutor.substitute(getValueReturnType, Variance.INVARIANT)
|
||||||
if (returnTypeInSystem != null) {
|
if (returnTypeInSystem != null) {
|
||||||
constraintSystem.addSubtypeConstraint(returnTypeInSystem, expectedType, FROM_COMPLETER.position())
|
constraintSystem.addSubtypeConstraint(returnTypeInSystem, expectedType, FROM_COMPLETER.position())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, descriptor)
|
addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, getValueDescriptor)
|
||||||
}
|
}
|
||||||
if (!variableDescriptor.isVar) return
|
if (!variableDescriptor.isVar) return
|
||||||
|
|
||||||
@@ -357,29 +456,49 @@ class DelegatedPropertyResolver(
|
|||||||
// 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 (variableDescriptor.returnType is DeferredType) return
|
if (variableDescriptor.returnType is DeferredType) return
|
||||||
|
|
||||||
val setMethodResults = getDelegatedPropertyConventionMethod(
|
val setValueResults = getGetSetValueMethod(
|
||||||
variableDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, delegateFunctionsScope,
|
variableDescriptor, delegateExpression, delegateType, traceToResolveConventionMethods, delegateFunctionsScope, dataFlowInfo,
|
||||||
dataFlowInfo, false, false
|
isGet = false, isComplete = false
|
||||||
)
|
)
|
||||||
|
if (conventionMethodFound(setValueResults)) {
|
||||||
if (conventionMethodFound(setMethodResults)) {
|
val setValueDescriptor = setValueResults.resultingDescriptor
|
||||||
val descriptor = setMethodResults.resultingDescriptor
|
val setValueParameters = setValueDescriptor.valueParameters
|
||||||
val valueParameters = descriptor.valueParameters
|
if (setValueParameters.size == 3) {
|
||||||
if (valueParameters.size == 3) {
|
|
||||||
val valueParameterForThis = valueParameters[2]
|
|
||||||
|
|
||||||
if (!noExpectedType(expectedType)) {
|
if (!noExpectedType(expectedType)) {
|
||||||
constraintSystem.addSubtypeConstraint(
|
val thisParameterType = setValueParameters[2].type
|
||||||
expectedType,
|
val substitutedThisParameterType = typeVariableSubstitutor.substitute(thisParameterType, Variance.INVARIANT)
|
||||||
typeVariableSubstitutor.substitute(valueParameterForThis.type, Variance.INVARIANT),
|
constraintSystem.addSubtypeConstraint(expectedType, substitutedThisParameterType, FROM_COMPLETER.position())
|
||||||
FROM_COMPLETER.position()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, descriptor)
|
addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, setValueDescriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getDelegateType(
|
||||||
|
byExpressionType: KotlinType,
|
||||||
|
constraintSystem: ConstraintSystem.Builder,
|
||||||
|
typeVariableSubstitutor: TypeSubstitutor,
|
||||||
|
traceToResolveConventionMethods: TemporaryBindingTrace
|
||||||
|
): KotlinType {
|
||||||
|
if (isOperatorCreateDelegateSupported) {
|
||||||
|
val createDelegateResults = getCreateDelegateMethod(
|
||||||
|
variableDescriptor, delegateExpression, byExpressionType,
|
||||||
|
traceToResolveConventionMethods, delegateFunctionsScope, dataFlowInfo
|
||||||
|
)
|
||||||
|
if (conventionMethodFound(createDelegateResults)) {
|
||||||
|
val createDelegateDescriptor = createDelegateResults.resultingDescriptor
|
||||||
|
val createDelegateReturnType = createDelegateDescriptor.returnType
|
||||||
|
if (createDelegateDescriptor.isOperator) {
|
||||||
|
addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, createDelegateDescriptor)
|
||||||
|
return createDelegateReturnType
|
||||||
|
?: throw AssertionError("No return type fore 'createDelegate' of ${delegateExpression.text}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return byExpressionType
|
||||||
|
}
|
||||||
|
|
||||||
private fun conventionMethodFound(results: OverloadResolutionResults<FunctionDescriptor>): Boolean =
|
private fun conventionMethodFound(results: OverloadResolutionResults<FunctionDescriptor>): Boolean =
|
||||||
results.isSuccess ||
|
results.isSuccess ||
|
||||||
results.isSingleResult && results.resultCode == OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH
|
results.isSingleResult && results.resultCode == OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve
|
package org.jetbrains.kotlin.resolve
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
@@ -42,22 +43,17 @@ object OperatorModifierChecker {
|
|||||||
|
|
||||||
val checkResult = OperatorChecks.check(functionDescriptor)
|
val checkResult = OperatorChecks.check(functionDescriptor)
|
||||||
if (checkResult.isSuccess) {
|
if (checkResult.isSuccess) {
|
||||||
val shouldUseOperatorRem = languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)
|
|
||||||
when (functionDescriptor.name) {
|
when (functionDescriptor.name) {
|
||||||
in COROUTINE_OPERATOR_NAMES -> {
|
in COROUTINE_OPERATOR_NAMES ->
|
||||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.Coroutines)) {
|
checkSupportsFeature(LanguageFeature.Coroutines, languageVersionSettings, diagnosticHolder, modifier)
|
||||||
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(modifier, LanguageFeature.Coroutines))
|
in REM_TO_MOD_OPERATION_NAMES.keys ->
|
||||||
}
|
checkSupportsFeature(LanguageFeature.OperatorRem, languageVersionSettings, diagnosticHolder, modifier)
|
||||||
}
|
OperatorNameConventions.CREATE_DELEGATE ->
|
||||||
|
checkSupportsFeature(LanguageFeature.OperatorCreateDelegate, languageVersionSettings, diagnosticHolder, modifier)
|
||||||
in REM_TO_MOD_OPERATION_NAMES.keys -> {
|
|
||||||
if (!shouldUseOperatorRem) {
|
|
||||||
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(modifier, LanguageFeature.OperatorRem))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (functionDescriptor.name in REM_TO_MOD_OPERATION_NAMES.values && shouldUseOperatorRem) {
|
if (functionDescriptor.name in REM_TO_MOD_OPERATION_NAMES.values
|
||||||
|
&& languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)) {
|
||||||
val newNameConvention = REM_TO_MOD_OPERATION_NAMES.inverse()[functionDescriptor.name]
|
val newNameConvention = REM_TO_MOD_OPERATION_NAMES.inverse()[functionDescriptor.name]
|
||||||
diagnosticHolder.report(Errors.DEPRECATED_BINARY_MOD.on(modifier, functionDescriptor, newNameConvention!!.asString()))
|
diagnosticHolder.report(Errors.DEPRECATED_BINARY_MOD.on(modifier, functionDescriptor, newNameConvention!!.asString()))
|
||||||
}
|
}
|
||||||
@@ -69,6 +65,12 @@ object OperatorModifierChecker {
|
|||||||
|
|
||||||
diagnosticHolder.report(Errors.INAPPLICABLE_OPERATOR_MODIFIER.on(modifier, errorDescription))
|
diagnosticHolder.report(Errors.INAPPLICABLE_OPERATOR_MODIFIER.on(modifier, errorDescription))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkSupportsFeature(feature: LanguageFeature, languageVersionSettings: LanguageVersionSettings, diagnosticHolder: DiagnosticSink, modifier: PsiElement) {
|
||||||
|
if (!languageVersionSettings.supportsFeature(feature)) {
|
||||||
|
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(modifier, feature))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val COROUTINE_OPERATOR_NAMES =
|
private val COROUTINE_OPERATOR_NAMES =
|
||||||
|
|||||||
+1
-1
@@ -140,7 +140,7 @@ class VariableTypeAndInitializerResolver(
|
|||||||
delegateExpression, property, variableDescriptor, scopeForInitializer, trace, dataFlowInfo)
|
delegateExpression, property, variableDescriptor, scopeForInitializer, trace, dataFlowInfo)
|
||||||
|
|
||||||
val delegateFunctionsScope = ScopeUtils.makeScopeForDelegateConventionFunctions(scopeForInitializer, variableDescriptor)
|
val delegateFunctionsScope = ScopeUtils.makeScopeForDelegateConventionFunctions(scopeForInitializer, variableDescriptor)
|
||||||
val getterReturnType = delegatedPropertyResolver.getDelegatedPropertyGetMethodReturnType(
|
val getterReturnType = delegatedPropertyResolver.getGetValueMethodReturnType(
|
||||||
variableDescriptor, delegateExpression, type, trace, delegateFunctionsScope, dataFlowInfo
|
variableDescriptor, delegateExpression, type, trace, delegateFunctionsScope, dataFlowInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Vendored
+13
@@ -0,0 +1,13 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
class Cell<out V>(val value: V)
|
||||||
|
|
||||||
|
class GenericDelegate<V>(val value: V)
|
||||||
|
|
||||||
|
operator fun <T> T.createDelegate(a: Any?, p: Any?) = GenericDelegate(this)
|
||||||
|
|
||||||
|
operator fun <W> GenericDelegate<W>.getValue(a: Any?, p: Any?) = Cell(value)
|
||||||
|
|
||||||
|
val test1: Cell<String> by "OK"
|
||||||
|
val test2: Cell<Any> by "OK"
|
||||||
|
val test3 by "OK"
|
||||||
Vendored
+23
@@ -0,0 +1,23 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val test1: Cell<kotlin.String>
|
||||||
|
public val test2: Cell<kotlin.Any>
|
||||||
|
public val test3: Cell<kotlin.String>
|
||||||
|
public operator fun </*0*/ T> T.createDelegate(/*0*/ a: kotlin.Any?, /*1*/ p: kotlin.Any?): GenericDelegate<T>
|
||||||
|
public operator fun </*0*/ W> GenericDelegate<W>.getValue(/*0*/ a: kotlin.Any?, /*1*/ p: kotlin.Any?): Cell<W>
|
||||||
|
|
||||||
|
public final class Cell</*0*/ out V> {
|
||||||
|
public constructor Cell</*0*/ out V>(/*0*/ value: V)
|
||||||
|
public final val value: V
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class GenericDelegate</*0*/ V> {
|
||||||
|
public constructor GenericDelegate</*0*/ V>(/*0*/ value: V)
|
||||||
|
public final val value: V
|
||||||
|
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
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
class StringDelegate(val s: String) {
|
||||||
|
operator fun getValue(a: Any?, p: KProperty<*>): Int = 42
|
||||||
|
}
|
||||||
|
|
||||||
|
// NB no operator
|
||||||
|
fun String.createDelegate(a: Any?, p: KProperty<*>) = StringDelegate(this)
|
||||||
|
|
||||||
|
operator fun String.getValue(a: Any?, p: KProperty<*>) = this
|
||||||
|
|
||||||
|
val test1: String by "OK"
|
||||||
|
val test2: Int by <!DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH!>"OK"<!>
|
||||||
|
val test3 by "OK"
|
||||||
|
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val test1: kotlin.String
|
||||||
|
public val test2: kotlin.Int
|
||||||
|
public val test3: kotlin.String
|
||||||
|
public fun kotlin.String.createDelegate(/*0*/ a: kotlin.Any?, /*1*/ p: kotlin.reflect.KProperty<*>): StringDelegate
|
||||||
|
public operator fun kotlin.String.getValue(/*0*/ a: kotlin.Any?, /*1*/ p: kotlin.reflect.KProperty<*>): kotlin.String
|
||||||
|
|
||||||
|
public final class StringDelegate {
|
||||||
|
public constructor StringDelegate(/*0*/ s: kotlin.String)
|
||||||
|
public final val s: kotlin.String
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final operator fun getValue(/*0*/ a: 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
|
||||||
|
}
|
||||||
Vendored
+10
@@ -0,0 +1,10 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
operator fun String.createDelegate(a: Any?, p: KProperty<*>) = this
|
||||||
|
operator fun String.getValue(a: Any?, p: KProperty<*>) = this
|
||||||
|
|
||||||
|
val test1: String by "OK"
|
||||||
|
|
||||||
|
val test2 by "OK"
|
||||||
Vendored
+6
@@ -0,0 +1,6 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val test1: kotlin.String
|
||||||
|
public val test2: kotlin.String
|
||||||
|
public operator fun kotlin.String.createDelegate(/*0*/ a: kotlin.Any?, /*1*/ p: kotlin.reflect.KProperty<*>): kotlin.String
|
||||||
|
public operator fun kotlin.String.getValue(/*0*/ a: kotlin.Any?, /*1*/ p: kotlin.reflect.KProperty<*>): kotlin.String
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
// !LANGUAGE: -OperatorCreateDelegate
|
||||||
|
|
||||||
|
class WrongDelegate(val x: Int) {
|
||||||
|
operator fun getValue(thisRef: Any?, prop: Any): Int = x
|
||||||
|
}
|
||||||
|
|
||||||
|
<!UNSUPPORTED_FEATURE(only available since Kotlin 1.1: operator createDelegate)!>operator<!> fun String.createDelegate(thisRef: Any?, prop: Any) = WrongDelegate(this.length)
|
||||||
|
|
||||||
|
operator fun String.getValue(thisRef: Any?, prop: Any) = this
|
||||||
|
|
||||||
|
val test1: String by "OK"
|
||||||
|
val test2: Int by <!DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH!>"OK"<!>
|
||||||
|
val test3 by "OK"
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val test1: kotlin.String
|
||||||
|
public val test2: kotlin.Int
|
||||||
|
public val test3: kotlin.String
|
||||||
|
public operator fun kotlin.String.createDelegate(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.Any): WrongDelegate
|
||||||
|
public operator fun kotlin.String.getValue(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.Any): kotlin.String
|
||||||
|
|
||||||
|
public final class WrongDelegate {
|
||||||
|
public constructor WrongDelegate(/*0*/ x: kotlin.Int)
|
||||||
|
public final val x: kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final operator fun getValue(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.Any): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -5758,6 +5758,39 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/tests/delegatedProperty/createDelegate")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class CreateDelegate extends AbstractDiagnosticsTest {
|
||||||
|
public void testAllFilesPresentInCreateDelegate() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/delegatedProperty/createDelegate"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("genericCreateDelegate.kt")
|
||||||
|
public void testGenericCreateDelegate() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/delegatedProperty/createDelegate/genericCreateDelegate.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("noOperatorModifierOnCreateDelegate.kt")
|
||||||
|
public void testNoOperatorModifierOnCreateDelegate() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/delegatedProperty/createDelegate/noOperatorModifierOnCreateDelegate.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleCreateDelegate.kt")
|
||||||
|
public void testSimpleCreateDelegate() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/delegatedProperty/createDelegate/simpleCreateDelegate.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsupportedOperatorCreateDelegate.kt")
|
||||||
|
public void testUnsupportedOperatorCreateDelegate() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/delegatedProperty/createDelegate/unsupportedOperatorCreateDelegate.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/delegatedProperty/inference")
|
@TestMetadata("compiler/testData/diagnostics/tests/delegatedProperty/inference")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ enum class LanguageFeature(val sinceVersion: LanguageVersion?) {
|
|||||||
DivisionByZeroInConstantExpressions(KOTLIN_1_1),
|
DivisionByZeroInConstantExpressions(KOTLIN_1_1),
|
||||||
InlineConstVals(KOTLIN_1_1),
|
InlineConstVals(KOTLIN_1_1),
|
||||||
OperatorRem(KOTLIN_1_1),
|
OperatorRem(KOTLIN_1_1),
|
||||||
|
OperatorCreateDelegate(KOTLIN_1_1),
|
||||||
|
|
||||||
// Experimental features
|
// Experimental features
|
||||||
MultiPlatformProjects(null),
|
MultiPlatformProjects(null),
|
||||||
|
|||||||
Reference in New Issue
Block a user