KT-4773: use receiver for delegated extension property
This commit is contained in:
+66
-20
@@ -28,8 +28,11 @@ import org.jetbrains.k2js.translate.general.AbstractTranslator
|
|||||||
import org.jetbrains.k2js.translate.general.Translation
|
import org.jetbrains.k2js.translate.general.Translation
|
||||||
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils
|
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils
|
||||||
|
|
||||||
import org.jetbrains.k2js.translate.context.Namer.getDelegateNameRef
|
import org.jetbrains.k2js.translate.context.Namer.*
|
||||||
|
import org.jetbrains.k2js.translate.utils.ast.*
|
||||||
import org.jetbrains.k2js.translate.utils.TranslationUtils.*
|
import org.jetbrains.k2js.translate.utils.TranslationUtils.*
|
||||||
|
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils.isExtension
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates single property /w accessors.
|
* Translates single property /w accessors.
|
||||||
@@ -113,12 +116,36 @@ private class PropertyTranslator(
|
|||||||
private fun generateDefaultGetterFunction(getterDescriptor: PropertyGetterDescriptor): JsFunction {
|
private fun generateDefaultGetterFunction(getterDescriptor: PropertyGetterDescriptor): JsFunction {
|
||||||
val delegatedCall = bindingContext().get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor)
|
val delegatedCall = bindingContext().get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor)
|
||||||
|
|
||||||
val value = if (delegatedCall != null)
|
if (delegatedCall != null) {
|
||||||
CallTranslator.translate(context(), delegatedCall, getDelegateNameRef(propertyName))
|
return generateDelegatedGetterFunction(getterDescriptor, delegatedCall)
|
||||||
else
|
}
|
||||||
backingFieldReference(context(), this.descriptor)
|
|
||||||
|
|
||||||
return simpleReturnFunction(context().getScopeForDescriptor(getterDescriptor.getContainingDeclaration()), value)
|
val scope = context().getScopeForDescriptor(getterDescriptor.getContainingDeclaration())
|
||||||
|
val result = backingFieldReference(context(), descriptor)
|
||||||
|
val body = JsBlock(JsReturn(result))
|
||||||
|
|
||||||
|
return JsFunction(scope, body, accessorDescription(getterDescriptor))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateDelegatedGetterFunction(
|
||||||
|
getterDescriptor: PropertyGetterDescriptor,
|
||||||
|
delegatedCall: ResolvedCall<FunctionDescriptor>
|
||||||
|
): JsFunction {
|
||||||
|
val scope = context().getScopeForDescriptor(getterDescriptor.getContainingDeclaration())
|
||||||
|
val function = JsFunction(scope, JsBlock(), accessorDescription(getterDescriptor))
|
||||||
|
|
||||||
|
val delegateRef = getDelegateNameRef(propertyName)
|
||||||
|
val delegatedJsCall = CallTranslator.translate(context(), delegatedCall, delegateRef)
|
||||||
|
|
||||||
|
if (isExtension(getterDescriptor)) {
|
||||||
|
val receiver = function.addParameter(getReceiverParameterName()).getName()
|
||||||
|
val arguments = (delegatedJsCall as JsInvocation).getArguments()
|
||||||
|
arguments.set(0, receiver.makeRef())
|
||||||
|
}
|
||||||
|
|
||||||
|
val returnResult = JsReturn(delegatedJsCall)
|
||||||
|
function.addStatement(returnResult)
|
||||||
|
return function
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateDefaultSetter(): JsPropertyInitializer {
|
private fun generateDefaultSetter(): JsPropertyInitializer {
|
||||||
@@ -127,25 +154,29 @@ private class PropertyTranslator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateDefaultSetterFunction(setterDescriptor: PropertySetterDescriptor): JsFunction {
|
private fun generateDefaultSetterFunction(setterDescriptor: PropertySetterDescriptor): JsFunction {
|
||||||
val jsFunction = JsFunction(context().getScopeForDescriptor(setterDescriptor.getContainingDeclaration()),
|
val containingScope = context().getScopeForDescriptor(setterDescriptor.getContainingDeclaration())
|
||||||
"setter for " + setterDescriptor.getName().asString())
|
val function = JsFunction(containingScope, JsBlock(), accessorDescription(setterDescriptor))
|
||||||
|
|
||||||
assert(setterDescriptor.getValueParameters().size() == 1, "Setter must have 1 parameter")
|
assert(setterDescriptor.getValueParameters().size() == 1, "Setter must have 1 parameter")
|
||||||
val valueParameterDescriptor = setterDescriptor.getValueParameters().get(0)
|
val correspondingPropertyName = setterDescriptor.getCorrespondingProperty().getName().asString()
|
||||||
val defaultParameter = JsParameter(jsFunction.getScope().declareTemporary())
|
val valueParameter = function.addParameter(correspondingPropertyName).getName()
|
||||||
val defaultParameterRef = defaultParameter.getName().makeRef()
|
val withAliased = context().innerContextWithAliased(setterDescriptor.getValueParameters().get(0), valueParameter.makeRef())
|
||||||
val contextWithAliased = context().innerContextWithAliased(valueParameterDescriptor, defaultParameterRef)
|
val delegatedCall = context().bindingContext().get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, setterDescriptor)
|
||||||
|
|
||||||
val delegatedCall = bindingContext().get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, setterDescriptor)
|
if (delegatedCall != null) {
|
||||||
|
val delegatedJsCall = CallTranslator.translate(withAliased, delegatedCall, getDelegateNameRef(correspondingPropertyName))
|
||||||
|
function.addStatement(delegatedJsCall.makeStmt())
|
||||||
|
|
||||||
val setExpression = if (delegatedCall != null)
|
if (isExtension(setterDescriptor)) {
|
||||||
CallTranslator.translate(contextWithAliased, delegatedCall, getDelegateNameRef(propertyName))
|
val receiver = function.addParameter(getReceiverParameterName(), 0).getName()
|
||||||
else
|
(delegatedJsCall as JsInvocation).getArguments().set(0, receiver.makeRef())
|
||||||
assignmentToBackingField(contextWithAliased, descriptor, defaultParameterRef)
|
}
|
||||||
|
} else {
|
||||||
|
val assignment = assignmentToBackingField(withAliased, descriptor, valueParameter.makeRef())
|
||||||
|
function.addStatement(assignment.makeStmt())
|
||||||
|
}
|
||||||
|
|
||||||
jsFunction.getParameters().add(defaultParameter)
|
return function
|
||||||
jsFunction.setBody(JsBlock(setExpression.makeStmt()))
|
|
||||||
return jsFunction
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateDefaultAccessor(accessorDescriptor: PropertyAccessorDescriptor, function: JsFunction): JsPropertyInitializer =
|
private fun generateDefaultAccessor(accessorDescriptor: PropertyAccessorDescriptor, function: JsFunction): JsPropertyInitializer =
|
||||||
@@ -153,4 +184,19 @@ private class PropertyTranslator(
|
|||||||
|
|
||||||
private fun translateCustomAccessor(expression: JetPropertyAccessor): JsPropertyInitializer =
|
private fun translateCustomAccessor(expression: JetPropertyAccessor): JsPropertyInitializer =
|
||||||
Translation.functionTranslator(expression, context()).translateAsEcma5PropertyDescriptor()
|
Translation.functionTranslator(expression, context()).translateAsEcma5PropertyDescriptor()
|
||||||
|
|
||||||
|
private fun accessorDescription(accessorDescriptor: PropertyAccessorDescriptor): String {
|
||||||
|
val accessorType =
|
||||||
|
when(accessorDescriptor) {
|
||||||
|
is PropertyGetterDescriptor ->
|
||||||
|
"getter"
|
||||||
|
is PropertySetterDescriptor ->
|
||||||
|
"setter"
|
||||||
|
else ->
|
||||||
|
throw IllegalArgumentException("Unknown accessor type ${accessorDescriptor.javaClass}")
|
||||||
|
}
|
||||||
|
|
||||||
|
val name = accessorDescriptor.getName().asString()
|
||||||
|
return "$accessorType for $name"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 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.k2js.translate.utils.ast
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsFunction
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsStatement
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsParameter
|
||||||
|
|
||||||
|
public fun JsFunction.addStatement(stmt: JsStatement) {
|
||||||
|
getBody().getStatements().add(stmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun JsFunction.addParameter(identifier: String, index: Int? = null): JsParameter {
|
||||||
|
val name = getScope().declareFreshName(identifier)
|
||||||
|
val parameter = JsParameter(name)
|
||||||
|
|
||||||
|
if (index == null) {
|
||||||
|
getParameters().add(parameter)
|
||||||
|
} else {
|
||||||
|
getParameters().add(index, parameter)
|
||||||
|
}
|
||||||
|
|
||||||
|
return parameter
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user