JS: introduce new flat JS declaration structure
This commit is contained in:
@@ -132,8 +132,7 @@ public abstract class JsScope {
|
|||||||
return names.containsKey(name);
|
return names.containsKey(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private boolean hasName(@NotNull String name) {
|
||||||
public boolean hasName(@NotNull String name) {
|
|
||||||
return hasOwnName(name) || (parent != null && parent.hasName(name));
|
return hasOwnName(name) || (parent != null && parent.hasName(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ import com.intellij.openapi.util.text.StringUtil
|
|||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||||
|
|||||||
@@ -3269,6 +3269,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/extensionProperty"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.ANY, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/extensionProperty"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.ANY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inClass.kt")
|
||||||
|
public void testInClass() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/extensionProperty/inClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("propertyWithGetterAndSetter.kt")
|
@TestMetadata("propertyWithGetterAndSetter.kt")
|
||||||
public void testPropertyWithGetterAndSetter() throws Exception {
|
public void testPropertyWithGetterAndSetter() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/extensionProperty/propertyWithGetterAndSetter.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/extensionProperty/propertyWithGetterAndSetter.kt");
|
||||||
@@ -3385,6 +3391,39 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inheritance/withInitializeMethod.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inheritance/withInitializeMethod.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("js/js.translator/testData/box/inheritance/interfaces")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Interfaces extends AbstractBoxJsTest {
|
||||||
|
@TestMetadata("abstractClassInheritingDefaultMethod.kt")
|
||||||
|
public void testAbstractClassInheritingDefaultMethod() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inheritance/interfaces/abstractClassInheritingDefaultMethod.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInInterfaces() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/inheritance/interfaces"), Pattern.compile("^([^_](.+))\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("withDefaultMethod.kt")
|
||||||
|
public void testWithDefaultMethod() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inheritance/interfaces/withDefaultMethod.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("withDefaultMethodFromSuperInterface.kt")
|
||||||
|
public void testWithDefaultMethodFromSuperInterface() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inheritance/interfaces/withDefaultMethodFromSuperInterface.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("withDefaultProperty.kt")
|
||||||
|
public void testWithDefaultProperty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inheritance/interfaces/withDefaultProperty.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("js/js.translator/testData/box/initialize")
|
@TestMetadata("js/js.translator/testData/box/initialize")
|
||||||
|
|||||||
+11
-11
@@ -21,10 +21,7 @@ import com.google.dart.compiler.backend.js.ast.JsName
|
|||||||
import com.google.dart.compiler.backend.js.ast.metadata.HasMetadata
|
import com.google.dart.compiler.backend.js.ast.metadata.HasMetadata
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind
|
import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
|
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
|
||||||
@@ -42,8 +39,6 @@ val CallInfo.callableDescriptor: CallableDescriptor
|
|||||||
return if (result is TypeAliasConstructorDescriptor) result.underlyingConstructorDescriptor else result
|
return if (result is TypeAliasConstructorDescriptor) result.underlyingConstructorDescriptor else result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CallInfo.isExtension(): Boolean = extensionReceiver != null
|
|
||||||
|
|
||||||
fun CallInfo.isNative(): Boolean = AnnotationsUtils.isNativeObject(callableDescriptor)
|
fun CallInfo.isNative(): Boolean = AnnotationsUtils.isNativeObject(callableDescriptor)
|
||||||
|
|
||||||
fun CallInfo.isSuperInvocation(): Boolean {
|
fun CallInfo.isSuperInvocation(): Boolean {
|
||||||
@@ -65,11 +60,16 @@ val VariableAccessInfo.variableName: JsName
|
|||||||
|
|
||||||
fun VariableAccessInfo.isGetAccess(): Boolean = value == null
|
fun VariableAccessInfo.isGetAccess(): Boolean = value == null
|
||||||
|
|
||||||
fun VariableAccessInfo.getAccessDescriptor(): DeclarationDescriptor {
|
fun VariableAccessInfo.getAccessDescriptor(): PropertyAccessorDescriptor {
|
||||||
val descriptor = variableDescriptor
|
val property = variableDescriptor as PropertyDescriptor
|
||||||
if (descriptor is PropertyDescriptor && (descriptor.isExtension || TranslationUtils.shouldGenerateAccessors(descriptor))) {
|
return if (isGetAccess()) property.getter!! else property.setter!!
|
||||||
val propertyAccessorDescriptor = if (isGetAccess()) descriptor.getter else descriptor.setter
|
}
|
||||||
return propertyAccessorDescriptor!!
|
|
||||||
|
fun VariableAccessInfo.getAccessDescriptorIfNeeded(): CallableDescriptor {
|
||||||
|
if (variableDescriptor is PropertyDescriptor &&
|
||||||
|
(variableDescriptor.isExtension || TranslationUtils.shouldAccessViaFunctions(variableDescriptor))
|
||||||
|
) {
|
||||||
|
return getAccessDescriptor()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return variableDescriptor
|
return variableDescriptor
|
||||||
|
|||||||
+4
-2
@@ -70,9 +70,11 @@ object CallTranslator {
|
|||||||
val isNative = AnnotationsUtils.isNativeObject(functionDescriptor)
|
val isNative = AnnotationsUtils.isNativeObject(functionDescriptor)
|
||||||
val hasSpreadOperator = false
|
val hasSpreadOperator = false
|
||||||
if (dispatchReceiver != null) {
|
if (dispatchReceiver != null) {
|
||||||
return DefaultFunctionCallCase.buildDefaultCallWithDispatchReceiver(argumentsInfo, dispatchReceiver, functionName, isNative, hasSpreadOperator)
|
return DefaultFunctionCallCase.buildDefaultCallWithDispatchReceiver(argumentsInfo, dispatchReceiver, functionName, isNative,
|
||||||
|
hasSpreadOperator)
|
||||||
} else {
|
} else {
|
||||||
return DefaultFunctionCallCase.buildDefaultCallWithoutReceiver(context, argumentsInfo, functionDescriptor, isNative, hasSpreadOperator)
|
return DefaultFunctionCallCase.buildDefaultCallWithoutReceiver(context, argumentsInfo, functionDescriptor, isNative,
|
||||||
|
hasSpreadOperator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-10
@@ -19,15 +19,13 @@ package org.jetbrains.kotlin.js.translate.callTranslator
|
|||||||
import com.google.dart.compiler.backend.js.ast.*
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
||||||
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
|
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
|
||||||
import org.jetbrains.kotlin.js.PredefinedAnnotation
|
import org.jetbrains.kotlin.js.PredefinedAnnotation
|
||||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.operation.OperatorTable
|
import org.jetbrains.kotlin.js.translate.operation.OperatorTable
|
||||||
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator
|
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator
|
||||||
|
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
|
||||||
@@ -83,7 +81,7 @@ object DefaultFunctionCallCase : FunctionCallCase() {
|
|||||||
return JsInvocation(JsNameRef(context.getNameForDescriptor(callableDescriptor)), argumentsInfo.translateArguments)
|
return JsInvocation(JsNameRef(context.getNameForDescriptor(callableDescriptor)), argumentsInfo.translateArguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
val functionRef = context.aliasOrValue(callableDescriptor) { context.getQualifiedReference(it) }
|
val functionRef = ReferenceTranslator.translateAsFQReference(callableDescriptor, context)
|
||||||
return JsInvocation(functionRef, argumentsInfo.translateArguments)
|
return JsInvocation(functionRef, argumentsInfo.translateArguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +101,7 @@ object DefaultFunctionCallCase : FunctionCallCase() {
|
|||||||
return JsInvocation(JsNameRef(functionName, extensionReceiver), argumentsInfo.translateArguments)
|
return JsInvocation(JsNameRef(functionName, extensionReceiver), argumentsInfo.translateArguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
val functionRef = context.aliasOrValue(callableDescriptor) { context.getQualifiedReference(it) }
|
val functionRef = ReferenceTranslator.translateAsFQReference(callableDescriptor, context)
|
||||||
|
|
||||||
val referenceToCall =
|
val referenceToCall =
|
||||||
if (callableDescriptor.visibility == Visibilities.LOCAL) {
|
if (callableDescriptor.visibility == Visibilities.LOCAL) {
|
||||||
@@ -214,9 +212,7 @@ object ConstructorCallCase : FunctionCallCase() {
|
|||||||
private inline fun FunctionCallInfo.doTranslate(
|
private inline fun FunctionCallInfo.doTranslate(
|
||||||
getArguments: CallArgumentTranslator.ArgumentsInfo.() -> List<JsExpression>
|
getArguments: CallArgumentTranslator.ArgumentsInfo.() -> List<JsExpression>
|
||||||
): JsExpression {
|
): JsExpression {
|
||||||
val fqName = context.getQualifiedReference(callableDescriptor)
|
val functionRef = ReferenceTranslator.translateAsFQReference(callableDescriptor, context)
|
||||||
val functionRef = if (isNative()) fqName else context.aliasOrValue(callableDescriptor) { fqName }
|
|
||||||
|
|
||||||
val invocationArguments = mutableListOf<JsExpression>()
|
val invocationArguments = mutableListOf<JsExpression>()
|
||||||
|
|
||||||
val constructorDescriptor = callableDescriptor as ClassConstructorDescriptor
|
val constructorDescriptor = callableDescriptor as ClassConstructorDescriptor
|
||||||
@@ -245,7 +241,7 @@ object SuperCallCase : FunctionCallCase() {
|
|||||||
|
|
||||||
override fun FunctionCallInfo.dispatchReceiver(): JsExpression {
|
override fun FunctionCallInfo.dispatchReceiver(): JsExpression {
|
||||||
// TODO: spread operator
|
// TODO: spread operator
|
||||||
val prototypeClass = pureFqn(Namer.getPrototypeName(), calleeOwner)
|
val prototypeClass = JsAstUtils.prototypeOf(calleeOwner)
|
||||||
val functionRef = Namer.getFunctionCallRef(JsNameRef(functionName, prototypeClass))
|
val functionRef = Namer.getFunctionCallRef(JsNameRef(functionName, prototypeClass))
|
||||||
return JsInvocation(functionRef, argumentsInfo.argsWithReceiver(dispatchReceiver!!))
|
return JsInvocation(functionRef, argumentsInfo.argsWithReceiver(dispatchReceiver!!))
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-29
@@ -26,13 +26,14 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||||
import org.jetbrains.kotlin.js.translate.context.Namer.getCapturedVarAccessor
|
import org.jetbrains.kotlin.js.translate.context.Namer.getCapturedVarAccessor
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
||||||
import org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure
|
import org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
object NativeVariableAccessCase : VariableAccessCase() {
|
object NativeVariableAccessCase : VariableAccessCase() {
|
||||||
override fun VariableAccessInfo.extensionReceiver(): JsExpression {
|
override fun VariableAccessInfo.extensionReceiver(): JsExpression {
|
||||||
return constructAccessExpression(JsNameRef(variableName, extensionReceiver!!))
|
return constructAccessExpression(JsNameRef(variableName, extensionReceiver!!))
|
||||||
@@ -40,8 +41,8 @@ object NativeVariableAccessCase : VariableAccessCase() {
|
|||||||
|
|
||||||
override fun VariableAccessInfo.dispatchReceiver(): JsExpression {
|
override fun VariableAccessInfo.dispatchReceiver(): JsExpression {
|
||||||
val descriptor = resolvedCall.resultingDescriptor
|
val descriptor = resolvedCall.resultingDescriptor
|
||||||
return if (descriptor is PropertyDescriptor && TranslationUtils.shouldGenerateAccessors(descriptor)) {
|
return if (descriptor is PropertyDescriptor && TranslationUtils.shouldAccessViaFunctions(descriptor)) {
|
||||||
val methodRef = context.getNameForDescriptor(getAccessDescriptor())
|
val methodRef = context.getNameForDescriptor(getAccessDescriptorIfNeeded())
|
||||||
JsInvocation(pureFqn(methodRef, dispatchReceiver!!), *additionalArguments.toTypedArray())
|
JsInvocation(pureFqn(methodRef, dispatchReceiver!!), *additionalArguments.toTypedArray())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -51,8 +52,8 @@ object NativeVariableAccessCase : VariableAccessCase() {
|
|||||||
|
|
||||||
override fun VariableAccessInfo.noReceivers(): JsExpression {
|
override fun VariableAccessInfo.noReceivers(): JsExpression {
|
||||||
val descriptor = resolvedCall.resultingDescriptor
|
val descriptor = resolvedCall.resultingDescriptor
|
||||||
return if (descriptor is PropertyDescriptor && TranslationUtils.shouldGenerateAccessors(descriptor)) {
|
return if (descriptor is PropertyDescriptor && TranslationUtils.shouldAccessViaFunctions(descriptor)) {
|
||||||
val methodRef = context.aliasOrValue(callableDescriptor) { context.getQualifiedReference(getAccessDescriptor()) }
|
val methodRef = context.aliasOrValue(callableDescriptor) { context.getQualifiedReference(getAccessDescriptorIfNeeded()) }
|
||||||
JsInvocation(methodRef, *additionalArguments.toTypedArray())
|
JsInvocation(methodRef, *additionalArguments.toTypedArray())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -63,32 +64,49 @@ object NativeVariableAccessCase : VariableAccessCase() {
|
|||||||
|
|
||||||
object DefaultVariableAccessCase : VariableAccessCase() {
|
object DefaultVariableAccessCase : VariableAccessCase() {
|
||||||
override fun VariableAccessInfo.noReceivers(): JsExpression {
|
override fun VariableAccessInfo.noReceivers(): JsExpression {
|
||||||
val descriptor = resolvedCall.resultingDescriptor
|
val variableDescriptor = this.variableDescriptor
|
||||||
if (descriptor is PropertyDescriptor && TranslationUtils.shouldGenerateAccessors(descriptor)) {
|
|
||||||
val methodRef = context.aliasOrValue(callableDescriptor) { context.getQualifiedReference(getAccessDescriptor()) }
|
if (variableDescriptor is PropertyDescriptor &&
|
||||||
|
!JsDescriptorUtils.isSimpleFinalProperty(variableDescriptor) &&
|
||||||
|
context.isFromCurrentModule(variableDescriptor)
|
||||||
|
) {
|
||||||
|
val methodRef = context.getInnerReference(getAccessDescriptor())
|
||||||
return JsInvocation(methodRef, *additionalArguments.toTypedArray())
|
return JsInvocation(methodRef, *additionalArguments.toTypedArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
val functionRef = context.aliasOrValue(callableDescriptor) {
|
val descriptor = resolvedCall.resultingDescriptor
|
||||||
context.getQualifiedReference(variableDescriptor)
|
if (descriptor is PropertyDescriptor && TranslationUtils.shouldAccessViaFunctions(descriptor)) {
|
||||||
|
val methodRef = context.aliasOrValue(callableDescriptor) { context.getQualifiedReference(getAccessDescriptorIfNeeded()) }
|
||||||
|
return JsInvocation(methodRef, *additionalArguments.toTypedArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
val ref =
|
if (descriptor is FakeCallableDescriptorForObject) {
|
||||||
if (isVarCapturedInClosure(context.bindingContext(), callableDescriptor)) {
|
return JsInvocation(pureFqn(context.getNameForObjectInstance (descriptor.getReferencedObject()), null))
|
||||||
getCapturedVarAccessor(functionRef)
|
}
|
||||||
} else {
|
|
||||||
functionRef
|
val functionRef = context.aliasOrValue(callableDescriptor) {
|
||||||
}
|
if (context.isFromCurrentModule(variableDescriptor)) {
|
||||||
|
context.getInnerReference(variableDescriptor)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val qualifier = context.getInnerReference(variableDescriptor.containingDeclaration)
|
||||||
|
val name = context.getNameForDescriptor(variableDescriptor)
|
||||||
|
JsNameRef(name, qualifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val ref = if (isVarCapturedInClosure(context.bindingContext(), callableDescriptor)) {
|
||||||
|
getCapturedVarAccessor(functionRef)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
functionRef
|
||||||
|
}
|
||||||
|
|
||||||
val localVariableDescriptor = resolvedCall.resultingDescriptor as? LocalVariableDescriptor
|
val localVariableDescriptor = resolvedCall.resultingDescriptor as? LocalVariableDescriptor
|
||||||
val accessorDescriptor = if (isGetAccess()) localVariableDescriptor?.getter else localVariableDescriptor?.setter
|
val accessorDescriptor = if (isGetAccess()) localVariableDescriptor?.getter else localVariableDescriptor?.setter
|
||||||
if (accessorDescriptor != null) {
|
if (accessorDescriptor != null) {
|
||||||
val funRef = JsNameRef(TranslationUtils.getAccessorFunctionName(accessorDescriptor), ref)
|
val funRef = JsNameRef(TranslationUtils.getAccessorFunctionName(accessorDescriptor), ref)
|
||||||
return if (isGetAccess()) {
|
return JsInvocation(funRef, *additionalArguments.toTypedArray())
|
||||||
JsInvocation(funRef)
|
|
||||||
} else {
|
|
||||||
JsInvocation(funRef, value!!)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return constructAccessExpression(ref)
|
return constructAccessExpression(ref)
|
||||||
@@ -96,8 +114,8 @@ object DefaultVariableAccessCase : VariableAccessCase() {
|
|||||||
|
|
||||||
override fun VariableAccessInfo.dispatchReceiver(): JsExpression {
|
override fun VariableAccessInfo.dispatchReceiver(): JsExpression {
|
||||||
val descriptor = resolvedCall.resultingDescriptor
|
val descriptor = resolvedCall.resultingDescriptor
|
||||||
return if (descriptor is PropertyDescriptor && TranslationUtils.shouldGenerateAccessors(descriptor)) {
|
return if (descriptor is PropertyDescriptor && TranslationUtils.shouldAccessViaFunctions(descriptor)) {
|
||||||
val callExpr = pureFqn(context.getNameForDescriptor(getAccessDescriptor()), dispatchReceiver!!)
|
val callExpr = pureFqn(context.getNameForDescriptor(getAccessDescriptorIfNeeded()), dispatchReceiver!!)
|
||||||
JsInvocation(callExpr, *additionalArguments.toTypedArray())
|
JsInvocation(callExpr, *additionalArguments.toTypedArray())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -110,12 +128,12 @@ object DefaultVariableAccessCase : VariableAccessCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun VariableAccessInfo.extensionReceiver(): JsExpression {
|
override fun VariableAccessInfo.extensionReceiver(): JsExpression {
|
||||||
val functionRef = context.aliasOrValue(callableDescriptor) { context.getQualifiedReference(getAccessDescriptor()) }
|
val functionRef = context.aliasOrValue(callableDescriptor) { context.getQualifiedReference(getAccessDescriptorIfNeeded()) }
|
||||||
return JsInvocation(functionRef, extensionReceiver!!, *additionalArguments.toTypedArray())
|
return JsInvocation(functionRef, extensionReceiver!!, *additionalArguments.toTypedArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun VariableAccessInfo.bothReceivers(): JsExpression {
|
override fun VariableAccessInfo.bothReceivers(): JsExpression {
|
||||||
val funRef = JsNameRef(context.getNameForDescriptor(getAccessDescriptor()), dispatchReceiver!!)
|
val funRef = JsNameRef(context.getNameForDescriptor(getAccessDescriptorIfNeeded()), dispatchReceiver!!)
|
||||||
return JsInvocation(funRef, extensionReceiver!!, *additionalArguments.toTypedArray())
|
return JsInvocation(funRef, extensionReceiver!!, *additionalArguments.toTypedArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,16 +168,16 @@ object SuperPropertyAccessCase : VariableAccessCase() {
|
|||||||
val variableName = context.program().getStringLiteral(this.variableName.ident)
|
val variableName = context.program().getStringLiteral(this.variableName.ident)
|
||||||
val descriptor = resolvedCall.resultingDescriptor
|
val descriptor = resolvedCall.resultingDescriptor
|
||||||
|
|
||||||
return if (descriptor is PropertyDescriptor && TranslationUtils.shouldGenerateAccessors(descriptor)) {
|
return if (descriptor is PropertyDescriptor && TranslationUtils.shouldAccessViaFunctions(descriptor)) {
|
||||||
val accessor = getAccessDescriptor()
|
val accessor = getAccessDescriptorIfNeeded()
|
||||||
val prototype = pureFqn(Namer.getPrototypeName(), context.getQualifiedReference(descriptor.containingDeclaration))
|
val prototype = pureFqn(Namer.getPrototypeName(), context.getInnerReference(descriptor.containingDeclaration))
|
||||||
val funRef = Namer.getFunctionCallRef(pureFqn(context.getNameForDescriptor(accessor), prototype))
|
val funRef = Namer.getFunctionCallRef(pureFqn(context.getNameForDescriptor(accessor), prototype))
|
||||||
val arguments = listOf(dispatchReceiver!!) + additionalArguments
|
val arguments = listOf(dispatchReceiver!!) + additionalArguments
|
||||||
JsInvocation(funRef, *arguments.toTypedArray())
|
JsInvocation(funRef, *arguments.toTypedArray())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val callExpr = if (isGetAccess()) context.namer().callGetProperty else context.namer().callSetProperty
|
val callExpr = if (isGetAccess()) context.namer().callGetProperty else context.namer().callSetProperty
|
||||||
val arguments = listOf(dispatchReceiver!!, calleeOwner, variableName) + additionalArguments
|
val arguments = listOf(dispatchReceiver!!, JsAstUtils.prototypeOf(calleeOwner), variableName) + additionalArguments
|
||||||
JsInvocation(callExpr, *arguments.toTypedArray())
|
JsInvocation(callExpr, *arguments.toTypedArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.js.translate.context
|
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*
|
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.staticRef
|
|
||||||
|
|
||||||
class DefinitionPlace(
|
|
||||||
private val scope: JsObjectScope,
|
|
||||||
private val fqName: JsExpression,
|
|
||||||
val properties: MutableList<JsPropertyInitializer>
|
|
||||||
) {
|
|
||||||
fun define(suggestedName: String, expression : JsExpression) = define(scope.declareFreshName(suggestedName), expression)
|
|
||||||
|
|
||||||
fun define(name: JsName, expression: JsExpression): JsNameRef {
|
|
||||||
if (expression is JsFunction) {
|
|
||||||
/** JsInliner should be able
|
|
||||||
* to find function by name */
|
|
||||||
name.staticRef = expression
|
|
||||||
}
|
|
||||||
|
|
||||||
properties.add(JsPropertyInitializer(name.makeRef(), expression))
|
|
||||||
return JsNameRef(name, fqName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
|||||||
import org.jetbrains.kotlin.js.naming.NameSuggestion;
|
import org.jetbrains.kotlin.js.naming.NameSuggestion;
|
||||||
import org.jetbrains.kotlin.js.naming.SuggestedName;
|
import org.jetbrains.kotlin.js.naming.SuggestedName;
|
||||||
import org.jetbrains.kotlin.js.resolve.JsPlatform;
|
import org.jetbrains.kotlin.js.resolve.JsPlatform;
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
@@ -77,10 +78,6 @@ public final class Namer {
|
|||||||
|
|
||||||
public static final String OUTER_FIELD_NAME = "$outer";
|
public static final String OUTER_FIELD_NAME = "$outer";
|
||||||
|
|
||||||
private static final String CLASS_OBJECT_NAME = "createClass";
|
|
||||||
private static final String ENUM_CLASS_OBJECT_NAME = "createEnumClass";
|
|
||||||
private static final String TRAIT_OBJECT_NAME = "createTrait";
|
|
||||||
private static final String OBJECT_OBJECT_NAME = "createObject";
|
|
||||||
private static final String CALLABLE_REF_FOR_MEMBER_FUNCTION_NAME = "getCallableRefForMemberFunction";
|
private static final String CALLABLE_REF_FOR_MEMBER_FUNCTION_NAME = "getCallableRefForMemberFunction";
|
||||||
private static final String CALLABLE_REF_FOR_EXTENSION_FUNCTION_NAME = "getCallableRefForExtensionFunction";
|
private static final String CALLABLE_REF_FOR_EXTENSION_FUNCTION_NAME = "getCallableRefForExtensionFunction";
|
||||||
private static final String CALLABLE_REF_FOR_LOCAL_EXTENSION_FUNCTION_NAME = "getCallableRefForLocalExtensionFunction";
|
private static final String CALLABLE_REF_FOR_LOCAL_EXTENSION_FUNCTION_NAME = "getCallableRefForLocalExtensionFunction";
|
||||||
@@ -89,13 +86,8 @@ public final class Namer {
|
|||||||
private static final String CALLABLE_REF_FOR_MEMBER_PROPERTY = "getCallableRefForMemberProperty";
|
private static final String CALLABLE_REF_FOR_MEMBER_PROPERTY = "getCallableRefForMemberProperty";
|
||||||
private static final String CALLABLE_REF_FOR_EXTENSION_PROPERTY = "getCallableRefForExtensionProperty";
|
private static final String CALLABLE_REF_FOR_EXTENSION_PROPERTY = "getCallableRefForExtensionProperty";
|
||||||
|
|
||||||
private static final String SETTER_PREFIX = "set_";
|
|
||||||
private static final String GETTER_PREFIX = "get_";
|
|
||||||
private static final String BACKING_FIELD_PREFIX = "$";
|
|
||||||
private static final String DELEGATE = "$delegate";
|
private static final String DELEGATE = "$delegate";
|
||||||
|
|
||||||
private static final String SUPER_METHOD_NAME = "baseInitializer";
|
|
||||||
|
|
||||||
private static final String ROOT_PACKAGE = "_";
|
private static final String ROOT_PACKAGE = "_";
|
||||||
|
|
||||||
private static final String RECEIVER_PARAMETER_NAME = "$receiver";
|
private static final String RECEIVER_PARAMETER_NAME = "$receiver";
|
||||||
@@ -113,6 +105,14 @@ public final class Namer {
|
|||||||
private static final JsNameRef JS_OBJECT_CREATE_FUNCTION = new JsNameRef("create", JS_OBJECT);
|
private static final JsNameRef JS_OBJECT_CREATE_FUNCTION = new JsNameRef("create", JS_OBJECT);
|
||||||
|
|
||||||
public static final String LOCAL_MODULE_PREFIX = "$module$";
|
public static final String LOCAL_MODULE_PREFIX = "$module$";
|
||||||
|
public static final String METADATA = "$metadata$";
|
||||||
|
public static final String METADATA_SUPERTYPES = "baseClasses";
|
||||||
|
|
||||||
|
public static final String OBJECT_INSTANCE_VAR_SUFFIX = "_instance";
|
||||||
|
public static final String OBJECT_INSTANCE_FUNCTION_SUFFIX = "_getInstance";
|
||||||
|
|
||||||
|
public static final String ENUM_NAME_FIELD = "name$";
|
||||||
|
public static final String ENUM_ORDINAL_FIELD = "ordinal$";
|
||||||
|
|
||||||
public static boolean isUndefined(@NotNull JsExpression expr) {
|
public static boolean isUndefined(@NotNull JsExpression expr) {
|
||||||
if (expr instanceof JsPrefixOperation) {
|
if (expr instanceof JsPrefixOperation) {
|
||||||
@@ -148,50 +148,11 @@ public final class Namer {
|
|||||||
return ROOT_PACKAGE;
|
return ROOT_PACKAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static JsNameRef superMethodNameRef(@NotNull JsName superClassJsName) {
|
|
||||||
return pureFqn(SUPER_METHOD_NAME, superClassJsName.makeRef());
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static String getNameForAccessor(@NotNull String propertyName, boolean isGetter, boolean useNativeAccessor) {
|
|
||||||
if (useNativeAccessor) {
|
|
||||||
return propertyName;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isGetter) {
|
|
||||||
return getNameForGetter(propertyName);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return getNameForSetter(propertyName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static String getKotlinBackingFieldName(@NotNull String propertyName) {
|
|
||||||
return getNameWithPrefix(propertyName, BACKING_FIELD_PREFIX);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static String getNameForGetter(@NotNull String propertyName) {
|
|
||||||
return getNameWithPrefix(propertyName, GETTER_PREFIX);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static String getNameForSetter(@NotNull String propertyName) {
|
|
||||||
return getNameWithPrefix(propertyName, SETTER_PREFIX);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static String getPrototypeName() {
|
public static String getPrototypeName() {
|
||||||
return PROTOTYPE_NAME;
|
return PROTOTYPE_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static JsNameRef getRefToPrototype(@NotNull JsExpression classOrTraitExpression) {
|
|
||||||
return pureFqn(getPrototypeName(), classOrTraitExpression);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static String getDelegatePrefix() {
|
public static String getDelegatePrefix() {
|
||||||
return DELEGATE;
|
return DELEGATE;
|
||||||
@@ -207,11 +168,6 @@ public final class Namer {
|
|||||||
return new JsNameRef(getDelegateName(propertyName), JsLiteral.THIS);
|
return new JsNameRef(getDelegateName(propertyName), JsLiteral.THIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static String getNameWithPrefix(@NotNull String name, @NotNull String prefix) {
|
|
||||||
return prefix + name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsNameRef getFunctionCallRef(@NotNull JsExpression functionExpression) {
|
public static JsNameRef getFunctionCallRef(@NotNull JsExpression functionExpression) {
|
||||||
return pureFqn(CALL_FUNCTION, functionExpression);
|
return pureFqn(CALL_FUNCTION, functionExpression);
|
||||||
@@ -224,7 +180,7 @@ public final class Namer {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsInvocation createObjectWithPrototypeFrom(JsNameRef referenceToClass) {
|
public static JsInvocation createObjectWithPrototypeFrom(JsNameRef referenceToClass) {
|
||||||
return new JsInvocation(JS_OBJECT_CREATE_FUNCTION, getRefToPrototype(referenceToClass));
|
return new JsInvocation(JS_OBJECT_CREATE_FUNCTION, JsAstUtils.prototypeOf(referenceToClass));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -245,18 +201,6 @@ public final class Namer {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private final JsObjectScope kotlinScope;
|
private final JsObjectScope kotlinScope;
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JsName classCreationMethodReference;
|
|
||||||
@NotNull
|
|
||||||
private final JsName enumClassCreationMethodName;
|
|
||||||
@NotNull
|
|
||||||
private final JsName interfaceCreationMethodName;
|
|
||||||
@NotNull
|
|
||||||
private final JsExpression definePackage;
|
|
||||||
@NotNull
|
|
||||||
private final JsExpression defineRootPackage;
|
|
||||||
@NotNull
|
|
||||||
private final JsName objectCreationMethodName;
|
|
||||||
@NotNull
|
|
||||||
private final JsName callableRefForMemberFunctionName;
|
private final JsName callableRefForMemberFunctionName;
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JsName callableRefForExtensionFunctionName;
|
private final JsName callableRefForExtensionFunctionName;
|
||||||
@@ -280,17 +224,10 @@ public final class Namer {
|
|||||||
|
|
||||||
private Namer(@NotNull JsScope rootScope) {
|
private Namer(@NotNull JsScope rootScope) {
|
||||||
kotlinScope = JsObjectScope(rootScope, "Kotlin standard object");
|
kotlinScope = JsObjectScope(rootScope, "Kotlin standard object");
|
||||||
interfaceCreationMethodName = kotlinScope.declareName(TRAIT_OBJECT_NAME);
|
|
||||||
|
|
||||||
definePackage = kotlin("definePackage");
|
|
||||||
defineRootPackage = kotlin("defineRootPackage");
|
|
||||||
|
|
||||||
callGetProperty = kotlin("callGetter");
|
callGetProperty = kotlin("callGetter");
|
||||||
callSetProperty = kotlin("callSetter");
|
callSetProperty = kotlin("callSetter");
|
||||||
|
|
||||||
classCreationMethodReference = kotlinScope.declareName(CLASS_OBJECT_NAME);
|
|
||||||
enumClassCreationMethodName = kotlinScope.declareName(ENUM_CLASS_OBJECT_NAME);
|
|
||||||
objectCreationMethodName = kotlinScope.declareName(OBJECT_OBJECT_NAME);
|
|
||||||
callableRefForMemberFunctionName = kotlinScope.declareName(CALLABLE_REF_FOR_MEMBER_FUNCTION_NAME);
|
callableRefForMemberFunctionName = kotlinScope.declareName(CALLABLE_REF_FOR_MEMBER_FUNCTION_NAME);
|
||||||
callableRefForExtensionFunctionName = kotlinScope.declareName(CALLABLE_REF_FOR_EXTENSION_FUNCTION_NAME);
|
callableRefForExtensionFunctionName = kotlinScope.declareName(CALLABLE_REF_FOR_EXTENSION_FUNCTION_NAME);
|
||||||
callableRefForLocalExtensionFunctionName = kotlinScope.declareName(CALLABLE_REF_FOR_LOCAL_EXTENSION_FUNCTION_NAME);
|
callableRefForLocalExtensionFunctionName = kotlinScope.declareName(CALLABLE_REF_FOR_LOCAL_EXTENSION_FUNCTION_NAME);
|
||||||
@@ -313,16 +250,6 @@ public final class Namer {
|
|||||||
return suggested.getNames().get(0);
|
return suggested.getNames().get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public JsExpression packageDefinitionMethodReference() {
|
|
||||||
return definePackage;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public JsExpression rootPackageDefinitionMethodReference() {
|
|
||||||
return defineRootPackage;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsExpression callableRefForMemberFunctionReference() {
|
public JsExpression callableRefForMemberFunctionReference() {
|
||||||
return kotlin(callableRefForMemberFunctionName);
|
return kotlin(callableRefForMemberFunctionName);
|
||||||
@@ -463,24 +390,6 @@ public final class Namer {
|
|||||||
return packageFqName.isRoot() ? getRootPackageName() : packageFqName.shortName().asString();
|
return packageFqName.isRoot() ? getRootPackageName() : packageFqName.shortName().asString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public JsExpression classCreateInvocation(@NotNull ClassDescriptor descriptor) {
|
|
||||||
switch (descriptor.getKind()) {
|
|
||||||
case INTERFACE:
|
|
||||||
return kotlin(interfaceCreationMethodName);
|
|
||||||
case ENUM_CLASS:
|
|
||||||
return kotlin(enumClassCreationMethodName);
|
|
||||||
case ENUM_ENTRY:
|
|
||||||
case OBJECT:
|
|
||||||
return kotlin(objectCreationMethodName);
|
|
||||||
case ANNOTATION_CLASS:
|
|
||||||
case CLASS:
|
|
||||||
return kotlin(classCreationMethodReference);
|
|
||||||
default:
|
|
||||||
throw new UnsupportedOperationException("Unsupported class kind: " + descriptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsExpression getUndefinedExpression() {
|
public static JsExpression getUndefinedExpression() {
|
||||||
return new JsPrefixOperation(JsUnaryOperator.VOID, JsNumberLiteral.ZERO);
|
return new JsPrefixOperation(JsUnaryOperator.VOID, JsNumberLiteral.ZERO);
|
||||||
@@ -488,12 +397,12 @@ public final class Namer {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsExpression getCallGetProperty() {
|
public JsExpression getCallGetProperty() {
|
||||||
return callGetProperty;
|
return callGetProperty.deepCopy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsExpression getCallSetProperty() {
|
public JsExpression getCallSetProperty() {
|
||||||
return callSetProperty;
|
return callSetProperty.deepCopy();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JsNameRef kotlinLong() {
|
public static JsNameRef kotlinLong() {
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ public final class StandardClasses {
|
|||||||
standardClasses.declare().forFQ("kotlin.Comparable").kotlinClass("Comparable");
|
standardClasses.declare().forFQ("kotlin.Comparable").kotlinClass("Comparable");
|
||||||
|
|
||||||
standardClasses.declare().forFQ("kotlin.Throwable").kotlinClass("Throwable");
|
standardClasses.declare().forFQ("kotlin.Throwable").kotlinClass("Throwable");
|
||||||
|
standardClasses.declare().forFQ("kotlin.Annotation").kotlinClass("Annotation");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+269
-15
@@ -27,7 +27,9 @@ import com.intellij.util.containers.ContainerUtil;
|
|||||||
import com.intellij.util.containers.hash.LinkedHashMap;
|
import com.intellij.util.containers.hash.LinkedHashMap;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||||
import org.jetbrains.kotlin.js.config.JsConfig;
|
import org.jetbrains.kotlin.js.config.JsConfig;
|
||||||
import org.jetbrains.kotlin.js.naming.NameSuggestion;
|
import org.jetbrains.kotlin.js.naming.NameSuggestion;
|
||||||
import org.jetbrains.kotlin.js.naming.SuggestedName;
|
import org.jetbrains.kotlin.js.naming.SuggestedName;
|
||||||
@@ -36,10 +38,12 @@ import org.jetbrains.kotlin.js.translate.context.generator.Rule;
|
|||||||
import org.jetbrains.kotlin.js.translate.intrinsic.Intrinsics;
|
import org.jetbrains.kotlin.js.translate.intrinsic.Intrinsics;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallsKt;
|
import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallsKt;
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -63,7 +67,8 @@ public final class StaticContext {
|
|||||||
Namer namer = Namer.newInstance(program.getRootScope());
|
Namer namer = Namer.newInstance(program.getRootScope());
|
||||||
Intrinsics intrinsics = new Intrinsics();
|
Intrinsics intrinsics = new Intrinsics();
|
||||||
StandardClasses standardClasses = StandardClasses.bindImplementations(namer.getKotlinScope());
|
StandardClasses standardClasses = StandardClasses.bindImplementations(namer.getKotlinScope());
|
||||||
return new StaticContext(program, bindingTrace, namer, intrinsics, standardClasses, program.getRootScope(), config,
|
JsFunction rootFunction = JsAstUtils.createFunctionWithEmptyBody(program.getScope());
|
||||||
|
return new StaticContext(program, rootFunction, bindingTrace, namer, intrinsics, standardClasses, program.getRootScope(), config,
|
||||||
moduleDescriptor);
|
moduleDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,10 +89,14 @@ public final class StaticContext {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private final JsScope rootScope;
|
private final JsScope rootScope;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Generator<JsName> innerNames = new InnerNameGenerator();
|
||||||
@NotNull
|
@NotNull
|
||||||
private final Map<FqName, JsName> packageNames = Maps.newHashMap();
|
private final Map<FqName, JsName> packageNames = Maps.newHashMap();
|
||||||
@NotNull
|
@NotNull
|
||||||
private final Generator<JsScope> scopes = new ScopeGenerator();
|
private final Generator<JsScope> scopes = new ScopeGenerator();
|
||||||
|
@NotNull
|
||||||
|
private final Generator<JsName> objectInstanceNames = new ObjectInstanceNameGenerator();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final Map<JsScope, JsFunction> scopeToFunction = Maps.newHashMap();
|
private final Map<JsScope, JsFunction> scopeToFunction = Maps.newHashMap();
|
||||||
@@ -124,9 +133,31 @@ public final class StaticContext {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private final JsScope rootPackageScope;
|
private final JsScope rootPackageScope;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private JsFunction rootFunction;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final List<JsStatement> declarationStatements = new ArrayList<JsStatement>();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final List<JsStatement> importStatements = new ArrayList<JsStatement>();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final List<JsStatement> exportStatements = new ArrayList<JsStatement>();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Set<ClassDescriptor> classes = new HashSet<ClassDescriptor>();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final ExportedPackage rootPackage = new ExportedPackage("");
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final JsObjectLiteral exportObject = rootPackage.objectLiteral;
|
||||||
|
|
||||||
//TODO: too many parameters in constructor
|
//TODO: too many parameters in constructor
|
||||||
private StaticContext(
|
private StaticContext(
|
||||||
@NotNull JsProgram program,
|
@NotNull JsProgram program,
|
||||||
|
@NotNull JsFunction rootFunction,
|
||||||
@NotNull BindingTrace bindingTrace,
|
@NotNull BindingTrace bindingTrace,
|
||||||
@NotNull Namer namer,
|
@NotNull Namer namer,
|
||||||
@NotNull Intrinsics intrinsics,
|
@NotNull Intrinsics intrinsics,
|
||||||
@@ -136,13 +167,15 @@ public final class StaticContext {
|
|||||||
@NotNull ModuleDescriptor moduleDescriptor
|
@NotNull ModuleDescriptor moduleDescriptor
|
||||||
) {
|
) {
|
||||||
this.program = program;
|
this.program = program;
|
||||||
|
this.rootFunction = rootFunction;
|
||||||
this.bindingTrace = bindingTrace;
|
this.bindingTrace = bindingTrace;
|
||||||
this.namer = namer;
|
this.namer = namer;
|
||||||
this.intrinsics = intrinsics;
|
this.intrinsics = intrinsics;
|
||||||
this.rootScope = rootScope;
|
this.rootScope = rootScope;
|
||||||
this.standardClasses = standardClasses;
|
this.standardClasses = standardClasses;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
currentModule = moduleDescriptor;
|
this.currentModule = moduleDescriptor;
|
||||||
|
this.rootFunction = rootFunction;
|
||||||
rootPackageScope = new JsObjectScope(rootScope, "<root package>", "root-package");
|
rootPackageScope = new JsObjectScope(rootScope, "<root package>", "root-package");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,11 +204,6 @@ public final class StaticContext {
|
|||||||
return namer;
|
return namer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private JsScope getRootScope() {
|
|
||||||
return rootScope;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Map<String, JsName> getImportedModules() {
|
public Map<String, JsName> getImportedModules() {
|
||||||
if (readOnlyImportedModules == null) {
|
if (readOnlyImportedModules == null) {
|
||||||
@@ -219,6 +247,10 @@ public final class StaticContext {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression buildQualifiedExpression(@NotNull DeclarationDescriptor descriptor) {
|
private JsExpression buildQualifiedExpression(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
if (descriptor instanceof ClassDescriptor && KotlinBuiltIns.isAny((ClassDescriptor) descriptor)) {
|
||||||
|
return new JsNameRef("Object");
|
||||||
|
}
|
||||||
|
|
||||||
SuggestedName suggested = nameSuggestion.suggest(descriptor);
|
SuggestedName suggested = nameSuggestion.suggest(descriptor);
|
||||||
if (suggested == null) {
|
if (suggested == null) {
|
||||||
ModuleDescriptor module = DescriptorUtils.getContainingModule(descriptor);
|
ModuleDescriptor module = DescriptorUtils.getContainingModule(descriptor);
|
||||||
@@ -288,6 +320,20 @@ public final class StaticContext {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JsName getInnerNameForDescriptor(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
JsName name = innerNames.get(descriptor.getOriginal());
|
||||||
|
assert name != null : "Must have inner name for descriptor";
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JsName getNameForObjectInstance(@NotNull ClassDescriptor descriptor) {
|
||||||
|
JsName name = objectInstanceNames.get(descriptor.getOriginal());
|
||||||
|
assert name != null : "Must have inner name for object instance";
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private List<JsName> getActualNameFromSuggested(@NotNull SuggestedName suggested) {
|
private List<JsName> getActualNameFromSuggested(@NotNull SuggestedName suggested) {
|
||||||
JsScope scope = getScopeForDescriptor(suggested.getScope());
|
JsScope scope = getScopeForDescriptor(suggested.getScope());
|
||||||
@@ -362,6 +408,100 @@ public final class StaticContext {
|
|||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final class InnerNameGenerator extends Generator<JsName> {
|
||||||
|
public InnerNameGenerator() {
|
||||||
|
addRule(new Rule<JsName>() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
if (descriptor instanceof ModuleDescriptor) {
|
||||||
|
return getModuleInnerName(descriptor);
|
||||||
|
}
|
||||||
|
if (descriptor instanceof LocalVariableDescriptor || descriptor instanceof ParameterDescriptor) {
|
||||||
|
return getNameForDescriptor(descriptor);
|
||||||
|
}
|
||||||
|
if (descriptor instanceof ConstructorDescriptor) {
|
||||||
|
if (((ConstructorDescriptor) descriptor).isPrimary()) {
|
||||||
|
return getInnerNameForDescriptor(((ConstructorDescriptor) descriptor).getConstructedClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JsName result = rootFunction.getScope().declareFreshName(getSuggestedName(descriptor));
|
||||||
|
ModuleDescriptor module = DescriptorUtilsKt.getModule(descriptor);
|
||||||
|
if (module != currentModule) {
|
||||||
|
importStatements.add(JsAstUtils.newVar(result, getQualifiedReference(descriptor)));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class ObjectInstanceNameGenerator extends Generator<JsName> {
|
||||||
|
public ObjectInstanceNameGenerator() {
|
||||||
|
addRule(new Rule<JsName>() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
String suggested = getSuggestedName(descriptor) + Namer.OBJECT_INSTANCE_FUNCTION_SUFFIX;
|
||||||
|
JsName result = rootFunction.getScope().declareFreshName(suggested);
|
||||||
|
ModuleDescriptor module = DescriptorUtilsKt.getModule(descriptor);
|
||||||
|
if (module != currentModule) {
|
||||||
|
importStatements.add(JsAstUtils.newVar(result, getQualifiedReference(descriptor)));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static String getSuggestedName(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
String suggestedName;
|
||||||
|
if (descriptor instanceof PropertyGetterDescriptor) {
|
||||||
|
PropertyGetterDescriptor getter = (PropertyGetterDescriptor) descriptor;
|
||||||
|
suggestedName = "get_" + getSuggestedName(getter.getCorrespondingProperty());
|
||||||
|
}
|
||||||
|
else if (descriptor instanceof PropertySetterDescriptor) {
|
||||||
|
PropertySetterDescriptor setter = (PropertySetterDescriptor) descriptor;
|
||||||
|
suggestedName = "set_" + getSuggestedName(setter.getCorrespondingProperty());
|
||||||
|
}
|
||||||
|
else if (descriptor instanceof ConstructorDescriptor) {
|
||||||
|
ConstructorDescriptor constructor = (ConstructorDescriptor) descriptor;
|
||||||
|
suggestedName = getSuggestedName(constructor.getContainingDeclaration()) + "_init";
|
||||||
|
descriptor = descriptor.getContainingDeclaration();
|
||||||
|
assert descriptor != null : "ConstructorDescriptor should have containing declaration: " + constructor;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (descriptor.getName().isSpecial()) {
|
||||||
|
if (descriptor instanceof ClassDescriptor) {
|
||||||
|
if (DescriptorUtils.isAnonymousObject(descriptor)) {
|
||||||
|
suggestedName = "ObjectLiteral";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
suggestedName = "Anonymous";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (descriptor instanceof FunctionDescriptor) {
|
||||||
|
suggestedName = "lambda";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
suggestedName = "anonymous";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
suggestedName = descriptor.getName().asString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(descriptor instanceof PackageFragmentDescriptor) && !DescriptorUtils.isTopLevelDeclaration(descriptor)) {
|
||||||
|
DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||||
|
assert container != null : "We just figured out that descriptor is not for a top-level declaration: " + descriptor;
|
||||||
|
suggestedName = getSuggestedName(container) + "$" + suggestedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return suggestedName;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsName declarePropertyOrPropertyAccessorName(@NotNull DeclarationDescriptor descriptor, @NotNull String name, boolean fresh) {
|
public JsName declarePropertyOrPropertyAccessorName(@NotNull DeclarationDescriptor descriptor, @NotNull String name, boolean fresh) {
|
||||||
JsScope scope = getEnclosingScope(descriptor);
|
JsScope scope = getEnclosingScope(descriptor);
|
||||||
@@ -384,7 +524,7 @@ public final class StaticContext {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (getSuperclass((ClassDescriptor) descriptor) == null) {
|
if (getSuperclass((ClassDescriptor) descriptor) == null) {
|
||||||
return getRootScope().innerObjectScope("Scope for class " + descriptor.getName());
|
return rootFunction.getScope();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -405,10 +545,7 @@ public final class StaticContext {
|
|||||||
Rule<JsScope> generateNewScopesForPackageDescriptors = new Rule<JsScope>() {
|
Rule<JsScope> generateNewScopesForPackageDescriptors = new Rule<JsScope>() {
|
||||||
@Override
|
@Override
|
||||||
public JsScope apply(@NotNull DeclarationDescriptor descriptor) {
|
public JsScope apply(@NotNull DeclarationDescriptor descriptor) {
|
||||||
if (!(descriptor instanceof PackageFragmentDescriptor)) {
|
return rootFunction.getScope();
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return getRootScope().innerObjectScope("Package " + descriptor.getName());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
//TODO: never get there
|
//TODO: never get there
|
||||||
@@ -426,7 +563,7 @@ public final class StaticContext {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsFunction correspondingFunction = JsAstUtils.createFunctionWithEmptyBody(getRootScope());
|
JsFunction correspondingFunction = JsAstUtils.createFunctionWithEmptyBody(rootFunction.getScope());
|
||||||
assert (!scopeToFunction.containsKey(correspondingFunction.getScope())) : "Scope to function value overridden for " + descriptor;
|
assert (!scopeToFunction.containsKey(correspondingFunction.getScope())) : "Scope to function value overridden for " + descriptor;
|
||||||
scopeToFunction.put(correspondingFunction.getScope(), correspondingFunction);
|
scopeToFunction.put(correspondingFunction.getScope(), correspondingFunction);
|
||||||
return correspondingFunction.getScope();
|
return correspondingFunction.getScope();
|
||||||
@@ -442,9 +579,15 @@ public final class StaticContext {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public JsExpression getModuleExpressionFor(@NotNull DeclarationDescriptor descriptor) {
|
public JsExpression getModuleExpressionFor(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
JsName name = getModuleInnerName(descriptor);
|
||||||
|
return name != null ? JsAstUtils.pureFqn(name, null) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private JsName getModuleInnerName(@NotNull DeclarationDescriptor descriptor) {
|
||||||
ModuleDescriptor module = DescriptorUtils.getContainingModule(descriptor);
|
ModuleDescriptor module = DescriptorUtils.getContainingModule(descriptor);
|
||||||
if (currentModule == module) {
|
if (currentModule == module) {
|
||||||
return pureFqn(Namer.getRootPackageName(), null);
|
return rootScope.declareName(Namer.getRootPackageName());
|
||||||
}
|
}
|
||||||
String moduleName;
|
String moduleName;
|
||||||
if (module == module.getBuiltIns().getBuiltInsModule()) {
|
if (module == module.getBuiltIns().getBuiltInsModule()) {
|
||||||
@@ -464,7 +607,7 @@ public final class StaticContext {
|
|||||||
importedModules.put(moduleName, moduleId);
|
importedModules.put(moduleName, moduleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return JsAstUtils.pureFqn(moduleId, null);
|
return moduleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JsExpression applySideEffects(JsExpression expression, DeclarationDescriptor descriptor) {
|
private static JsExpression applySideEffects(JsExpression expression, DeclarationDescriptor descriptor) {
|
||||||
@@ -493,4 +636,115 @@ public final class StaticContext {
|
|||||||
public Map<ClassDescriptor, List<DeferredCallSite>> getDeferredCallSites() {
|
public Map<ClassDescriptor, List<DeferredCallSite>> getDeferredCallSites() {
|
||||||
return deferredCallSites;
|
return deferredCallSites;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JsFunction getRootFunction() {
|
||||||
|
return rootFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public List<JsStatement> getDeclarationStatements() {
|
||||||
|
return declarationStatements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRootStatement(@NotNull JsStatement statement) {
|
||||||
|
declarationStatements.add(statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addClass(@NotNull ClassDescriptor classDescriptor) {
|
||||||
|
classes.add(classDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void export(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||||
|
if (descriptor instanceof ConstructorDescriptor) {
|
||||||
|
ConstructorDescriptor constructor = (ConstructorDescriptor) descriptor;
|
||||||
|
container = constructor.getConstructedClass().getContainingDeclaration();
|
||||||
|
}
|
||||||
|
if (!(container instanceof PackageFragmentDescriptor)) {
|
||||||
|
throw new IllegalArgumentException("Declaration " + descriptor + " is not a top-level declaration");
|
||||||
|
}
|
||||||
|
|
||||||
|
PackageFragmentDescriptor packageDescriptor = (PackageFragmentDescriptor) container;
|
||||||
|
ExportedPackage exportedPackage = rootPackage;
|
||||||
|
for (Name packageName : packageDescriptor.getFqName().pathSegments()) {
|
||||||
|
exportedPackage = exportedPackage.getSubpackage(packageName.asString());
|
||||||
|
}
|
||||||
|
|
||||||
|
JsExpression initializerExpr = DeclarationExporter.exportDeclaration(this, descriptor, exportStatements);
|
||||||
|
if (initializerExpr != null) {
|
||||||
|
JsPropertyInitializer initializer = new JsPropertyInitializer(
|
||||||
|
getNameForDescriptor(descriptor).makeRef(), initializerExpr);
|
||||||
|
exportedPackage.objectLiteral.getPropertyInitializers().add(initializer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public NameSuggestion getNameSuggestion() {
|
||||||
|
return nameSuggestion;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public ModuleDescriptor getCurrentModule() {
|
||||||
|
return currentModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void postProcess() {
|
||||||
|
rootFunction.getBody().getStatements().addAll(importStatements);
|
||||||
|
addClassPrototypes();
|
||||||
|
rootFunction.getBody().getStatements().addAll(declarationStatements);
|
||||||
|
|
||||||
|
JsName rootPackageName = rootFunction.getScope().declareName(Namer.getRootPackageName());
|
||||||
|
rootFunction.getBody().getStatements().add(JsAstUtils.newVar(rootPackageName, exportObject));
|
||||||
|
rootFunction.getBody().getStatements().addAll(exportStatements);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addClassPrototypes() {
|
||||||
|
Set<ClassDescriptor> visited = new HashSet<ClassDescriptor>();
|
||||||
|
for (ClassDescriptor cls : classes) {
|
||||||
|
addClassPrototypes(cls, visited);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addClassPrototypes(@NotNull ClassDescriptor cls, @NotNull Set<ClassDescriptor> visited) {
|
||||||
|
if (DescriptorUtilsKt.getModule(cls) != currentModule) return;
|
||||||
|
if (!visited.add(cls)) return;
|
||||||
|
|
||||||
|
ClassDescriptor superclass = DescriptorUtilsKt.getSuperClassNotAny(cls);
|
||||||
|
if (superclass != null) {
|
||||||
|
addClassPrototypes(superclass, visited);
|
||||||
|
|
||||||
|
List<JsStatement> statements = rootFunction.getBody().getStatements();
|
||||||
|
|
||||||
|
JsExpression superPrototype = JsAstUtils.prototypeOf(new JsNameRef(getInnerNameForDescriptor(superclass)));
|
||||||
|
JsExpression superPrototypeInstance = new JsInvocation(new JsNameRef("create", "Object"), superPrototype);
|
||||||
|
JsExpression classRef = new JsNameRef(getInnerNameForDescriptor(cls));
|
||||||
|
JsExpression prototype = JsAstUtils.prototypeOf(classRef);
|
||||||
|
statements.add(JsAstUtils.assignment(prototype, superPrototypeInstance).makeStmt());
|
||||||
|
|
||||||
|
JsExpression constructorRef = new JsNameRef("constructor", prototype.deepCopy());
|
||||||
|
statements.add(JsAstUtils.assignment(constructorRef, classRef.deepCopy()).makeStmt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ExportedPackage {
|
||||||
|
@NotNull final String name;
|
||||||
|
@NotNull final Map<String, ExportedPackage> subpackages = new HashMap<String, ExportedPackage>();
|
||||||
|
@NotNull final JsObjectLiteral objectLiteral = new JsObjectLiteral(true);
|
||||||
|
|
||||||
|
public ExportedPackage(@NotNull String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public ExportedPackage getSubpackage(@NotNull String name) {
|
||||||
|
ExportedPackage subpackage = subpackages.get(name);
|
||||||
|
if (subpackage == null) {
|
||||||
|
subpackage = new ExportedPackage(name);
|
||||||
|
subpackages.put(name, subpackage);
|
||||||
|
objectLiteral.getPropertyInitializers().add(new JsPropertyInitializer(new JsNameRef(name), subpackage.objectLiteral));
|
||||||
|
}
|
||||||
|
return subpackage;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+85
-39
@@ -24,12 +24,14 @@ import org.jetbrains.kotlin.descriptors.*;
|
|||||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor;
|
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor;
|
||||||
import org.jetbrains.kotlin.js.config.JsConfig;
|
import org.jetbrains.kotlin.js.config.JsConfig;
|
||||||
import org.jetbrains.kotlin.js.translate.intrinsic.Intrinsics;
|
import org.jetbrains.kotlin.js.translate.intrinsic.Intrinsics;
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
import org.jetbrains.kotlin.psi.KtExpression;
|
import org.jetbrains.kotlin.psi.KtExpression;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -52,17 +54,19 @@ public class TranslationContext {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private final TranslationContext parent;
|
private final TranslationContext parent;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final DefinitionPlace definitionPlace;
|
|
||||||
@Nullable
|
|
||||||
private final DeclarationDescriptor declarationDescriptor;
|
private final DeclarationDescriptor declarationDescriptor;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final ClassDescriptor classDescriptor;
|
private final ClassDescriptor classDescriptor;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static TranslationContext rootContext(@NotNull StaticContext staticContext, JsFunction rootFunction) {
|
public static TranslationContext rootContext(
|
||||||
DynamicContext rootDynamicContext = DynamicContext.rootContext(rootFunction.getScope(), rootFunction.getBody());
|
@NotNull StaticContext staticContext,
|
||||||
|
@NotNull JsFunction rootFunction
|
||||||
|
) {
|
||||||
|
JsBlock block = new JsBlock(staticContext.getDeclarationStatements());
|
||||||
|
DynamicContext rootDynamicContext = DynamicContext.rootContext(rootFunction.getScope(), block);
|
||||||
AliasingContext rootAliasingContext = AliasingContext.getCleanContext();
|
AliasingContext rootAliasingContext = AliasingContext.getCleanContext();
|
||||||
return new TranslationContext(null, staticContext, rootDynamicContext, rootAliasingContext, null, null, null);
|
return new TranslationContext(null, staticContext, rootDynamicContext, rootAliasingContext, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Map<JsExpression, TemporaryConstVariable> expressionToTempConstVariableCache = new HashMap<JsExpression, TemporaryConstVariable>();
|
private final Map<JsExpression, TemporaryConstVariable> expressionToTempConstVariableCache = new HashMap<JsExpression, TemporaryConstVariable>();
|
||||||
@@ -73,7 +77,6 @@ public class TranslationContext {
|
|||||||
@NotNull DynamicContext dynamicContext,
|
@NotNull DynamicContext dynamicContext,
|
||||||
@NotNull AliasingContext aliasingContext,
|
@NotNull AliasingContext aliasingContext,
|
||||||
@Nullable UsageTracker usageTracker,
|
@Nullable UsageTracker usageTracker,
|
||||||
@Nullable DefinitionPlace definitionPlace,
|
|
||||||
@Nullable DeclarationDescriptor declarationDescriptor
|
@Nullable DeclarationDescriptor declarationDescriptor
|
||||||
) {
|
) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
@@ -81,7 +84,6 @@ public class TranslationContext {
|
|||||||
this.staticContext = staticContext;
|
this.staticContext = staticContext;
|
||||||
this.aliasingContext = aliasingContext;
|
this.aliasingContext = aliasingContext;
|
||||||
this.usageTracker = usageTracker;
|
this.usageTracker = usageTracker;
|
||||||
this.definitionPlace = definitionPlace;
|
|
||||||
this.declarationDescriptor = declarationDescriptor;
|
this.declarationDescriptor = declarationDescriptor;
|
||||||
if (declarationDescriptor instanceof ClassDescriptor) {
|
if (declarationDescriptor instanceof ClassDescriptor) {
|
||||||
this.classDescriptor = (ClassDescriptor) declarationDescriptor;
|
this.classDescriptor = (ClassDescriptor) declarationDescriptor;
|
||||||
@@ -119,27 +121,25 @@ public class TranslationContext {
|
|||||||
aliasingContext = this.aliasingContext.inner();
|
aliasingContext = this.aliasingContext.inner();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TranslationContext(this, this.staticContext, dynamicContext, aliasingContext, this.usageTracker, null, descriptor);
|
return new TranslationContext(this, this.staticContext, dynamicContext, aliasingContext, this.usageTracker, descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public TranslationContext newFunctionBodyWithUsageTracker(@NotNull JsFunction fun, @NotNull MemberDescriptor descriptor) {
|
public TranslationContext newFunctionBodyWithUsageTracker(@NotNull JsFunction fun, @NotNull MemberDescriptor descriptor) {
|
||||||
DynamicContext dynamicContext = DynamicContext.newContext(fun.getScope(), fun.getBody());
|
DynamicContext dynamicContext = DynamicContext.newContext(fun.getScope(), fun.getBody());
|
||||||
UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor, fun.getScope());
|
UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor, fun.getScope());
|
||||||
return new TranslationContext(this, this.staticContext, dynamicContext, this.aliasingContext.inner(), usageTracker,
|
return new TranslationContext(this, this.staticContext, dynamicContext, this.aliasingContext.inner(), usageTracker, descriptor);
|
||||||
this.definitionPlace, descriptor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public TranslationContext innerWithUsageTracker(@NotNull JsScope scope, @NotNull MemberDescriptor descriptor) {
|
public TranslationContext innerWithUsageTracker(@NotNull JsScope scope, @NotNull MemberDescriptor descriptor) {
|
||||||
UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor, scope);
|
UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor, scope);
|
||||||
return new TranslationContext(this, staticContext, dynamicContext, aliasingContext.inner(), usageTracker, definitionPlace,
|
return new TranslationContext(this, staticContext, dynamicContext, aliasingContext.inner(), usageTracker, descriptor);
|
||||||
descriptor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public TranslationContext innerBlock(@NotNull JsBlock block) {
|
public TranslationContext innerBlock(@NotNull JsBlock block) {
|
||||||
return new TranslationContext(this, staticContext, dynamicContext.innerBlock(block), aliasingContext, usageTracker, null,
|
return new TranslationContext(this, staticContext, dynamicContext.innerBlock(block), aliasingContext, usageTracker,
|
||||||
this.declarationDescriptor);
|
this.declarationDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,14 +149,18 @@ public class TranslationContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public TranslationContext newDeclaration(@NotNull DeclarationDescriptor descriptor, @Nullable DefinitionPlace place) {
|
public TranslationContext newDeclaration(@NotNull DeclarationDescriptor descriptor) {
|
||||||
DynamicContext dynamicContext = DynamicContext.newContext(getScopeForDescriptor(descriptor), getBlockForDescriptor(descriptor));
|
JsBlock innerBlock = getBlockForDescriptor(descriptor);
|
||||||
return new TranslationContext(this, staticContext, dynamicContext, aliasingContext, usageTracker, place, descriptor);
|
if (innerBlock == null) {
|
||||||
|
innerBlock = dynamicContext.jsBlock();
|
||||||
|
}
|
||||||
|
DynamicContext dynamicContext = DynamicContext.newContext(getScopeForDescriptor(descriptor), innerBlock);
|
||||||
|
return new TranslationContext(this, staticContext, dynamicContext, aliasingContext, usageTracker, descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private TranslationContext innerWithAliasingContext(AliasingContext aliasingContext) {
|
private TranslationContext innerWithAliasingContext(AliasingContext aliasingContext) {
|
||||||
return new TranslationContext(this, staticContext, dynamicContext, aliasingContext, usageTracker, null, declarationDescriptor);
|
return new TranslationContext(this, staticContext, dynamicContext, aliasingContext, usageTracker, declarationDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -174,13 +178,13 @@ public class TranslationContext {
|
|||||||
return this.innerWithAliasingContext(aliasingContext.withDescriptorsAliased(aliases));
|
return this.innerWithAliasingContext(aliasingContext.withDescriptorsAliased(aliases));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nullable
|
||||||
private JsBlock getBlockForDescriptor(@NotNull DeclarationDescriptor descriptor) {
|
private JsBlock getBlockForDescriptor(@NotNull DeclarationDescriptor descriptor) {
|
||||||
if (descriptor instanceof CallableDescriptor) {
|
if (descriptor instanceof CallableDescriptor) {
|
||||||
return getFunctionObject((CallableDescriptor) descriptor).getBody();
|
return getFunctionObject((CallableDescriptor) descriptor).getBody();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new JsBlock();
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,8 +215,13 @@ public class TranslationContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsName getNameForPackage(@NotNull FqName fqName) {
|
public JsName getInnerNameForDescriptor(@NotNull DeclarationDescriptor descriptor) {
|
||||||
return staticContext.getNameForPackage(fqName);
|
return staticContext.getInnerNameForDescriptor(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JsName getNameForObjectInstance(@NotNull ClassDescriptor descriptor) {
|
||||||
|
return staticContext.getNameForObjectInstance(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -225,6 +234,11 @@ public class TranslationContext {
|
|||||||
return staticContext.getQualifiedReference(descriptor);
|
return staticContext.getQualifiedReference(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JsNameRef getInnerReference(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
return JsAstUtils.pureFqn(getInnerNameForDescriptor(descriptor), null);
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsNameRef getQualifiedReference(@NotNull FqName packageFqName) {
|
public JsNameRef getQualifiedReference(@NotNull FqName packageFqName) {
|
||||||
return staticContext.getQualifiedReference(packageFqName);
|
return staticContext.getQualifiedReference(packageFqName);
|
||||||
@@ -358,7 +372,9 @@ public class TranslationContext {
|
|||||||
return JsLiteral.THIS;
|
return JsLiteral.THIS;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return getQualifiedReference(descriptor.getContainingDeclaration());
|
ClassDescriptor objectDescriptor = (ClassDescriptor) descriptor.getContainingDeclaration();
|
||||||
|
JsExpression instanceFunctionRef = JsAstUtils.pureFqn(getNameForObjectInstance(objectDescriptor), null);
|
||||||
|
return new JsInvocation(instanceFunctionRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,7 +397,7 @@ public class TranslationContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isConstructorOrDirectScope(DeclarationDescriptor descriptor) {
|
private boolean isConstructorOrDirectScope(DeclarationDescriptor descriptor) {
|
||||||
if (declarationDescriptor instanceof ClassDescriptor && !DescriptorUtils.isCompanionObject(declarationDescriptor)) {
|
if (declarationDescriptor instanceof ClassDescriptor) {
|
||||||
return descriptor == declarationDescriptor;
|
return descriptor == declarationDescriptor;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -402,8 +418,7 @@ public class TranslationContext {
|
|||||||
return thisExpression;
|
return thisExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassDescriptor parentDescriptor = parent.classDescriptor;
|
if (classDescriptor != parent.classDescriptor) {
|
||||||
if (classDescriptor != parentDescriptor) {
|
|
||||||
return new JsNameRef(Namer.OUTER_FIELD_NAME, parent.getDispatchReceiverPath(cls, thisExpression));
|
return new JsNameRef(Namer.OUTER_FIELD_NAME, parent.getDispatchReceiverPath(cls, thisExpression));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -411,20 +426,6 @@ public class TranslationContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public DefinitionPlace getDefinitionPlace() {
|
|
||||||
if (definitionPlace != null) return definitionPlace;
|
|
||||||
if (parent != null) return parent.getDefinitionPlace();
|
|
||||||
|
|
||||||
throw new AssertionError("Can not find definition place from rootContext(definitionPlace and parent is null)");
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public JsNameRef define(DeclarationDescriptor descriptor, JsExpression expression) {
|
|
||||||
String suggestedName = TranslationUtils.getSuggestedNameForInnerDeclaration(staticContext, descriptor);
|
|
||||||
return getDefinitionPlace().define(suggestedName, expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private JsNameRef captureIfNeedAndGetCapturedName(DeclarationDescriptor descriptor) {
|
private JsNameRef captureIfNeedAndGetCapturedName(DeclarationDescriptor descriptor) {
|
||||||
if (usageTracker != null) {
|
if (usageTracker != null) {
|
||||||
@@ -560,4 +561,49 @@ public class TranslationContext {
|
|||||||
public JsExpression getModuleExpressionFor(@NotNull DeclarationDescriptor descriptor) {
|
public JsExpression getModuleExpressionFor(@NotNull DeclarationDescriptor descriptor) {
|
||||||
return staticContext.getModuleExpressionFor(descriptor);
|
return staticContext.getModuleExpressionFor(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JsFunction getRootFunction() {
|
||||||
|
return staticContext.getRootFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRootStatement(@NotNull JsStatement statement) {
|
||||||
|
staticContext.addRootStatement(statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JsFunction defineTopLevelFunction(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
JsFunction function = createTopLevelFunction(descriptor);
|
||||||
|
addRootStatement(function.makeStmt());
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JsName createGlobalName(@NotNull String suggestedName) {
|
||||||
|
return staticContext.getRootFunction().getScope().declareFreshName(suggestedName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JsFunction createTopLevelFunction(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
JsFunction function = createTopLevelAnonymousFunction(descriptor);
|
||||||
|
function.setName(staticContext.getInnerNameForDescriptor(descriptor));
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JsFunction createTopLevelAnonymousFunction(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
return new JsFunction(getRootFunction().getScope(), new JsBlock(), descriptor.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addClass(@NotNull ClassDescriptor classDescriptor) {
|
||||||
|
staticContext.addClass(classDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void export(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
staticContext.export(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFromCurrentModule(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
return staticContext.getCurrentModule() == DescriptorUtilsKt.getModule(descriptor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:JvmName("DeclarationExporter")
|
||||||
|
package org.jetbrains.kotlin.js.translate.context
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
|
||||||
|
|
||||||
|
fun StaticContext.exportDeclaration(declaration: DeclarationDescriptor, additionalStatements: MutableList<in JsStatement>): JsExpression? {
|
||||||
|
return when {
|
||||||
|
declaration is ClassDescriptor && declaration.kind == ClassKind.OBJECT -> {
|
||||||
|
exportObject(declaration, additionalStatements)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
declaration is PropertyDescriptor -> {
|
||||||
|
exportProperty(declaration, additionalStatements)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
getInnerNameForDescriptor(declaration).makeRef()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun StaticContext.exportObject(declaration: ClassDescriptor, additionalStatements: MutableList<in JsStatement>) {
|
||||||
|
val suggestedName = nameSuggestion.suggest(declaration)!!
|
||||||
|
val qualifier = getQualifiedReference(suggestedName.scope)
|
||||||
|
val name = getNameForDescriptor(declaration)
|
||||||
|
additionalStatements += JsAstUtils.defineGetter(program, qualifier, name.ident, getNameForObjectInstance(declaration).makeRef())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun StaticContext.exportProperty(declaration: PropertyDescriptor, additionalStatements: MutableList<in JsStatement>) {
|
||||||
|
val propertyLiteral = JsObjectLiteral(true)
|
||||||
|
|
||||||
|
val suggestedName = nameSuggestion.suggest(declaration)!!
|
||||||
|
val qualifier = getQualifiedReference(suggestedName.scope)
|
||||||
|
val name = getNameForDescriptor(declaration).ident
|
||||||
|
|
||||||
|
val getterBody: JsExpression = if (JsDescriptorUtils.isSimpleFinalProperty(declaration)) {
|
||||||
|
val accessToField = JsReturn(getInnerNameForDescriptor(declaration).makeRef())
|
||||||
|
JsFunction(rootFunction.scope, JsBlock(accessToField), "$declaration getter")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
getInnerNameForDescriptor(declaration.getter!!).makeRef()
|
||||||
|
}
|
||||||
|
propertyLiteral.propertyInitializers += JsPropertyInitializer(JsNameRef("get"), getterBody)
|
||||||
|
|
||||||
|
if (declaration.isVar) {
|
||||||
|
val setterBody: JsExpression = if (JsDescriptorUtils.isSimpleFinalProperty(declaration)) {
|
||||||
|
val statements = mutableListOf<JsStatement>()
|
||||||
|
val function = JsFunction(rootFunction.scope, JsBlock(statements), "$declaration setter")
|
||||||
|
val valueName = function.scope.declareFreshName("value")
|
||||||
|
function.parameters += JsParameter(valueName)
|
||||||
|
statements += JsAstUtils.assignment(getInnerNameForDescriptor(declaration).makeRef(), valueName.makeRef()).makeStmt()
|
||||||
|
function
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
getInnerNameForDescriptor(declaration.setter!!).makeRef()
|
||||||
|
}
|
||||||
|
propertyLiteral.propertyInitializers += JsPropertyInitializer(JsNameRef("set"), setterBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
additionalStatements += JsAstUtils.defineProperty(qualifier, name, propertyLiteral, program).makeStmt()
|
||||||
|
}
|
||||||
+116
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 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.js.translate.declaration
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsExpression
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
|
import org.jetbrains.kotlin.js.translate.general.Translation
|
||||||
|
import org.jetbrains.kotlin.js.translate.general.TranslatorVisitor
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.BindingUtils
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty
|
||||||
|
|
||||||
|
abstract class AbstractDeclarationVisitor : TranslatorVisitor<Unit>() {
|
||||||
|
override fun emptyResult(context: TranslationContext) { }
|
||||||
|
|
||||||
|
override fun visitClassOrObject(classOrObject: KtClassOrObject, context: TranslationContext) {
|
||||||
|
ClassTranslator.translate(classOrObject, context)
|
||||||
|
val descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), classOrObject)
|
||||||
|
addClass(descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitProperty(expression: KtProperty, context: TranslationContext) {
|
||||||
|
val descriptor = BindingUtils.getPropertyDescriptor(context.bindingContext(), expression)
|
||||||
|
if (descriptor.modality === Modality.ABSTRACT) return
|
||||||
|
|
||||||
|
val propertyContext = context.newDeclaration(descriptor)
|
||||||
|
|
||||||
|
val defaultTranslator = DefaultPropertyTranslator(descriptor, context, getBackingFieldReference(descriptor))
|
||||||
|
val getter = descriptor.getter!!
|
||||||
|
val getterExpr = if (expression.hasCustomGetter()) {
|
||||||
|
translateFunction(getter, expression.getter!!, propertyContext)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val function = context.getFunctionObject(getter)
|
||||||
|
defaultTranslator.generateDefaultGetterFunction(getter, function)
|
||||||
|
function
|
||||||
|
}
|
||||||
|
|
||||||
|
val setterExpr = if (descriptor.isVar) {
|
||||||
|
val setter = descriptor.setter!!
|
||||||
|
if (expression.hasCustomSetter()) {
|
||||||
|
translateFunction(setter, expression.setter!!, propertyContext)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val function = context.getFunctionObject(setter)
|
||||||
|
defaultTranslator.generateDefaultSetterFunction(setter, function)
|
||||||
|
function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TranslationUtils.shouldAccessViaFunctions(descriptor) || descriptor.isExtensionProperty) {
|
||||||
|
addFunction(descriptor.getter!!, getterExpr)
|
||||||
|
descriptor.setter?.let { addFunction(it, setterExpr!!) }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addProperty(descriptor, getterExpr, setterExpr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitNamedFunction(expression: KtNamedFunction, context: TranslationContext) {
|
||||||
|
val descriptor = BindingUtils.getFunctionDescriptor(context.bindingContext(), expression)
|
||||||
|
if (descriptor.modality === Modality.ABSTRACT) return
|
||||||
|
|
||||||
|
addFunction(descriptor, translateFunction(descriptor, expression, context))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTypeAlias(typeAlias: KtTypeAlias, data: TranslationContext?) {}
|
||||||
|
|
||||||
|
private fun translateFunction(
|
||||||
|
descriptor: FunctionDescriptor,
|
||||||
|
expression: KtDeclarationWithBody,
|
||||||
|
context: TranslationContext
|
||||||
|
): JsExpression {
|
||||||
|
val innerContext = context.newDeclaration(descriptor)
|
||||||
|
innerContext.getInnerNameForDescriptor(descriptor)
|
||||||
|
val function = context.getFunctionObject(descriptor)
|
||||||
|
return Translation.functionTranslator(expression, innerContext, function).translateAsMethod()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun addClass(descriptor: ClassDescriptor)
|
||||||
|
|
||||||
|
protected abstract fun addFunction(
|
||||||
|
descriptor: FunctionDescriptor,
|
||||||
|
expression: JsExpression
|
||||||
|
)
|
||||||
|
|
||||||
|
protected abstract fun addProperty(
|
||||||
|
descriptor: PropertyDescriptor,
|
||||||
|
getter: JsExpression,
|
||||||
|
setter: JsExpression?
|
||||||
|
)
|
||||||
|
|
||||||
|
protected abstract fun getBackingFieldReference(descriptor: PropertyDescriptor): JsExpression
|
||||||
|
}
|
||||||
+174
-101
@@ -17,7 +17,6 @@
|
|||||||
package org.jetbrains.kotlin.js.translate.declaration
|
package org.jetbrains.kotlin.js.translate.declaration
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
import com.intellij.util.SmartList
|
|
||||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||||
import org.jetbrains.kotlin.backend.common.bridges.Bridge
|
import org.jetbrains.kotlin.backend.common.bridges.Bridge
|
||||||
import org.jetbrains.kotlin.backend.common.bridges.generateBridgesForFunctionDescriptor
|
import org.jetbrains.kotlin.backend.common.bridges.generateBridgesForFunctionDescriptor
|
||||||
@@ -30,21 +29,19 @@ import org.jetbrains.kotlin.js.translate.context.*
|
|||||||
import org.jetbrains.kotlin.js.translate.expression.FunctionTranslator
|
import org.jetbrains.kotlin.js.translate.expression.FunctionTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
|
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.initializer.ClassInitializerTranslator
|
import org.jetbrains.kotlin.js.translate.initializer.ClassInitializerTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils
|
import org.jetbrains.kotlin.js.translate.utils.*
|
||||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getClassDescriptor
|
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getClassDescriptor
|
||||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getPropertyDescriptorForConstructorParameter
|
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getPropertyDescriptorForConstructorParameter
|
||||||
import org.jetbrains.kotlin.js.translate.utils.FunctionBodyTranslator
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes
|
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes
|
||||||
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getPrimaryConstructorParameters
|
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getPrimaryConstructorParameters
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.simpleReturnFunction
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.generateDelegateCall
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.toInvocationWith
|
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.toInvocationWith
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtSecondaryConstructor
|
import org.jetbrains.kotlin.psi.KtSecondaryConstructor
|
||||||
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.*
|
import org.jetbrains.kotlin.resolve.DescriptorUtils.getClassDescriptorForType
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils.getClassDescriptorForTypeConstructor
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
import org.jetbrains.kotlin.types.CommonSupertypes.topologicallySortSuperclassesAndRecordAllInstances
|
import org.jetbrains.kotlin.types.CommonSupertypes.topologicallySortSuperclassesAndRecordAllInstances
|
||||||
import org.jetbrains.kotlin.types.SimpleType
|
import org.jetbrains.kotlin.types.SimpleType
|
||||||
import org.jetbrains.kotlin.types.TypeConstructor
|
import org.jetbrains.kotlin.types.TypeConstructor
|
||||||
@@ -60,20 +57,13 @@ class ClassTranslator private constructor(
|
|||||||
) : AbstractTranslator(context) {
|
) : AbstractTranslator(context) {
|
||||||
|
|
||||||
private val descriptor = getClassDescriptor(context.bindingContext(), classDeclaration)
|
private val descriptor = getClassDescriptor(context.bindingContext(), classDeclaration)
|
||||||
private val invocationArguments = mutableListOf<JsExpression>()
|
|
||||||
private val secondaryConstructors = mutableListOf<ConstructorInfo>()
|
private val secondaryConstructors = mutableListOf<ConstructorInfo>()
|
||||||
private val secondaryConstructorProperties = mutableListOf<JsPropertyInitializer>()
|
|
||||||
private var primaryConstructor: ConstructorInfo? = null
|
private var primaryConstructor: ConstructorInfo? = null
|
||||||
private lateinit var definitionPlace: DefinitionPlace
|
private lateinit var cachedInstanceName: JsName
|
||||||
|
private val metadataLiteral = JsObjectLiteral(true)
|
||||||
|
|
||||||
private fun translate(): TranslationResult {
|
private fun translate() {
|
||||||
generateClassCreateInvocationArguments()
|
generateClassCreateInvocationArguments()
|
||||||
|
|
||||||
val classNameRef = context().getNameForDescriptor(descriptor).makeRef()
|
|
||||||
val classCreation = JsInvocation(context().namer().classCreateInvocation(descriptor), invocationArguments)
|
|
||||||
|
|
||||||
val properties = listOf(JsPropertyInitializer(classNameRef, classCreation)) + secondaryConstructorProperties
|
|
||||||
return TranslationResult(properties, definitionPlace)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isTrait(): Boolean = descriptor.kind == ClassKind.INTERFACE
|
private fun isTrait(): Boolean = descriptor.kind == ClassKind.INTERFACE
|
||||||
@@ -81,35 +71,35 @@ class ClassTranslator private constructor(
|
|||||||
private fun isAnnotation(): Boolean = descriptor.kind == ClassKind.ANNOTATION_CLASS
|
private fun isAnnotation(): Boolean = descriptor.kind == ClassKind.ANNOTATION_CLASS
|
||||||
|
|
||||||
private fun generateClassCreateInvocationArguments() {
|
private fun generateClassCreateInvocationArguments() {
|
||||||
val properties = SmartList<JsPropertyInitializer>()
|
|
||||||
val staticProperties = SmartList<JsPropertyInitializer>()
|
|
||||||
|
|
||||||
val qualifiedReference = context().getQualifiedReference(descriptor)
|
|
||||||
val scope = context().getScopeForDescriptor(descriptor)
|
val scope = context().getScopeForDescriptor(descriptor)
|
||||||
val definitionPlace = DefinitionPlace(scope as JsObjectScope, qualifiedReference, staticProperties)
|
val context = context().newDeclaration(descriptor)
|
||||||
val context = context().newDeclaration(descriptor, definitionPlace)
|
|
||||||
|
|
||||||
invocationArguments += getSuperclassReferences(context)
|
val constructorFunction = context.defineTopLevelFunction(descriptor)
|
||||||
|
|
||||||
val nonConstructorContext = context.innerWithUsageTracker(scope, descriptor)
|
val nonConstructorContext = context.innerWithUsageTracker(scope, descriptor)
|
||||||
nonConstructorContext.startDeclaration()
|
nonConstructorContext.startDeclaration()
|
||||||
val delegationTranslator = DelegationTranslator(classDeclaration, nonConstructorContext)
|
val delegationTranslator = DelegationTranslator(classDeclaration, nonConstructorContext)
|
||||||
translatePropertiesAsConstructorParameters(nonConstructorContext, properties)
|
translatePropertiesAsConstructorParameters(nonConstructorContext)
|
||||||
val bodyVisitor = DeclarationBodyVisitor(properties, staticProperties, scope)
|
val bodyVisitor = DeclarationBodyVisitor(descriptor, nonConstructorContext)
|
||||||
bodyVisitor.traverseContainer(classDeclaration, nonConstructorContext)
|
bodyVisitor.traverseContainer(classDeclaration, nonConstructorContext)
|
||||||
delegationTranslator.generateDelegated(properties)
|
constructorFunction.body.statements += bodyVisitor.initializerStatements
|
||||||
|
delegationTranslator.generateDelegated()
|
||||||
|
|
||||||
translatePrimaryConstructor(context, delegationTranslator)
|
translatePrimaryConstructor(constructorFunction, context, delegationTranslator)
|
||||||
|
addMetadataObject()
|
||||||
|
addMetadataType()
|
||||||
|
context.addClass(descriptor)
|
||||||
|
addSuperclassReferences()
|
||||||
classDeclaration.getSecondaryConstructors().forEach { generateSecondaryConstructor(context, it) }
|
classDeclaration.getSecondaryConstructors().forEach { generateSecondaryConstructor(context, it) }
|
||||||
generatedBridgeMethods(properties)
|
|
||||||
|
|
||||||
if (descriptor.isData) {
|
if (descriptor.kind != ClassKind.INTERFACE) {
|
||||||
JsDataClassGenerator(classDeclaration, context, properties).generate()
|
addInterfaceDefaultMembers()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isEnumClass(descriptor)) {
|
generatedBridgeMethods()
|
||||||
val enumEntries = JsObjectLiteral(bodyVisitor.enumEntryList, true)
|
|
||||||
invocationArguments += simpleReturnFunction(nonConstructorContext.getScopeForDescriptor(descriptor), enumEntries)
|
if (descriptor.isData) {
|
||||||
|
JsDataClassGenerator(classDeclaration, context).generate()
|
||||||
}
|
}
|
||||||
|
|
||||||
emitConstructors(nonConstructorContext, nonConstructorContext.endDeclaration())
|
emitConstructors(nonConstructorContext, nonConstructorContext.endDeclaration())
|
||||||
@@ -117,40 +107,63 @@ class ClassTranslator private constructor(
|
|||||||
addClosureParameters(constructor, nonConstructorContext)
|
addClosureParameters(constructor, nonConstructorContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExpressionVisitor.visitObjectLiteralExpression uses DefinitionPlace of the translated class to generate call to
|
if (isObjectLike()) {
|
||||||
// super constructor. Sometimes, when generating super call, we may translate another anonymous class passed as an
|
addObjectMethods()
|
||||||
// argument. This class will be declared in the DefinitionPlace and put it static properties. See full explanation
|
|
||||||
// in ExpressionVisitor.visitObjectLiteralExpression
|
|
||||||
// TODO: It's a hack, we should think how to generate staticProperties lazily, whenever somebody tries to put
|
|
||||||
// definition into DefinitionPlace.
|
|
||||||
val hasStaticProperties = !staticProperties.isEmpty() || DescriptorUtils.isAnonymousObject(descriptor)
|
|
||||||
if (!properties.isEmpty() || hasStaticProperties) {
|
|
||||||
if (properties.isEmpty()) {
|
|
||||||
invocationArguments += JsLiteral.NULL
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// about "prototype" - see http://code.google.com/p/jsdoc-toolkit/wiki/TagLends
|
|
||||||
invocationArguments += JsDocComment(JsAstUtils.LENDS_JS_DOC_TAG, JsNameRef("prototype", qualifiedReference))
|
|
||||||
invocationArguments += JsObjectLiteral(properties, true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (hasStaticProperties) {
|
|
||||||
invocationArguments += JsDocComment(JsAstUtils.LENDS_JS_DOC_TAG, qualifiedReference)
|
|
||||||
invocationArguments += JsObjectLiteral(staticProperties, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.definitionPlace = definitionPlace
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translatePrimaryConstructor(classContext: TranslationContext, delegationTranslator: DelegationTranslator) {
|
private fun translatePrimaryConstructor(
|
||||||
if (isTrait()) return
|
constructorFunction: JsFunction,
|
||||||
|
classContext: TranslationContext,
|
||||||
|
delegationTranslator: DelegationTranslator
|
||||||
|
) {
|
||||||
|
if (!isTrait()) {
|
||||||
|
val constructorContext = classContext.innerWithUsageTracker(constructorFunction.scope, descriptor)
|
||||||
|
if (isObjectLike()) {
|
||||||
|
addObjectCache(constructorFunction.body.statements)
|
||||||
|
}
|
||||||
|
ClassInitializerTranslator(classDeclaration, constructorContext, constructorFunction)
|
||||||
|
.generateInitializeMethod(delegationTranslator)
|
||||||
|
primaryConstructor = ConstructorInfo(constructorFunction, constructorContext, descriptor)
|
||||||
|
|
||||||
val scope = JsFunctionScope(classContext.scope(), "$descriptor: primary constructor")
|
if (descriptor.kind == ClassKind.ENUM_CLASS) {
|
||||||
val constructorContext = classContext.innerWithUsageTracker(scope, descriptor)
|
addEnumClassParameters(constructorFunction)
|
||||||
val initializer = ClassInitializerTranslator(classDeclaration, constructorContext).generateInitializeMethod(delegationTranslator)
|
}
|
||||||
invocationArguments += initializer
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.primaryConstructor = ConstructorInfo(initializer, constructorContext, descriptor)
|
private fun addEnumClassParameters(constructorFunction: JsFunction) {
|
||||||
|
val nameParamName = constructorFunction.scope.declareFreshName("name")
|
||||||
|
val ordinalParamName = constructorFunction.scope.declareFreshName("ordinal")
|
||||||
|
constructorFunction.parameters += listOf(JsParameter(nameParamName), JsParameter(ordinalParamName))
|
||||||
|
|
||||||
|
constructorFunction.body.statements += JsAstUtils.assignmentToThisField(Namer.ENUM_NAME_FIELD, nameParamName.makeRef())
|
||||||
|
constructorFunction.body.statements += JsAstUtils.assignmentToThisField(Namer.ENUM_ORDINAL_FIELD, ordinalParamName.makeRef())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isObjectLike() = when (descriptor.kind) {
|
||||||
|
ClassKind.OBJECT,
|
||||||
|
ClassKind.ENUM_ENTRY -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addMetadataObject() {
|
||||||
|
context().addRootStatement(JsAstUtils.assignment(createMetadataRef(), metadataLiteral).makeStmt())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createMetadataRef() = JsNameRef(Namer.METADATA, context().getInnerReference(descriptor))
|
||||||
|
|
||||||
|
private fun addMetadataType() {
|
||||||
|
val kotlinType = JsNameRef("TYPE", Namer.KOTLIN_NAME)
|
||||||
|
val typeRef = when {
|
||||||
|
DescriptorUtils.isInterface(descriptor) -> JsNameRef("TRAIT", kotlinType)
|
||||||
|
DescriptorUtils.isObject(descriptor) -> JsNameRef("OBJECT", kotlinType)
|
||||||
|
else -> JsNameRef("CLASS", kotlinType)
|
||||||
|
}
|
||||||
|
val typeIndex = JsInvocation(JsNameRef("newClassIndex", Namer.KOTLIN_NAME))
|
||||||
|
|
||||||
|
metadataLiteral.propertyInitializers += JsPropertyInitializer(JsNameRef("type"), typeRef)
|
||||||
|
metadataLiteral.propertyInitializers += JsPropertyInitializer(JsNameRef("classIndex"), typeIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateSecondaryConstructor(classContext: TranslationContext, constructor: KtSecondaryConstructor) {
|
private fun generateSecondaryConstructor(classContext: TranslationContext, constructor: KtSecondaryConstructor) {
|
||||||
@@ -177,12 +190,12 @@ class ClassTranslator private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Translate constructor body
|
// Translate constructor body
|
||||||
val constructorInitializer = FunctionTranslator.newInstance(constructor, context).translateAsMethod()
|
val constructorInitializer = context.defineTopLevelFunction(constructorDescriptor)
|
||||||
val constructorFunction = constructorInitializer.valueExpr as JsFunction
|
FunctionTranslator.newInstance(constructor, context, constructorInitializer).translateAsMethodWithoutMetadata()
|
||||||
|
|
||||||
// Translate super/this call
|
// Translate super/this call
|
||||||
val superCallGenerators = mutableListOf<(MutableList<JsStatement>) -> Unit>()
|
val superCallGenerators = mutableListOf<(MutableList<JsStatement>) -> Unit>()
|
||||||
val referenceToClass = context.getQualifiedReference(classDescriptor)
|
val referenceToClass = context.getInnerReference(classDescriptor)
|
||||||
|
|
||||||
superCallGenerators += { it += FunctionBodyTranslator.setDefaultValueForArguments(constructorDescriptor, context) }
|
superCallGenerators += { it += FunctionBodyTranslator.setDefaultValueForArguments(constructorDescriptor, context) }
|
||||||
|
|
||||||
@@ -194,11 +207,11 @@ class ClassTranslator private constructor(
|
|||||||
val leadingArgs = mutableListOf<JsExpression>()
|
val leadingArgs = mutableListOf<JsExpression>()
|
||||||
|
|
||||||
if (outerClassName != null) {
|
if (outerClassName != null) {
|
||||||
constructorFunction.parameters.add(0, JsParameter(outerClassName))
|
constructorInitializer.parameters.add(0, JsParameter(outerClassName))
|
||||||
leadingArgs += outerClassName.makeRef()
|
leadingArgs += outerClassName.makeRef()
|
||||||
}
|
}
|
||||||
|
|
||||||
constructorFunction.parameters += JsParameter(thisName)
|
constructorInitializer.parameters += JsParameter(thisName)
|
||||||
|
|
||||||
// Generate super/this call to insert to beginning of the function
|
// Generate super/this call to insert to beginning of the function
|
||||||
val resolvedCall = BindingContextUtils.getDelegationConstructorCall(context.bindingContext(), constructorDescriptor)
|
val resolvedCall = BindingContextUtils.getDelegationConstructorCall(context.bindingContext(), constructorDescriptor)
|
||||||
@@ -223,18 +236,17 @@ class ClassTranslator private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructorFunction.body.statements += JsReturn(thisNameRef)
|
constructorInitializer.body.statements += JsReturn(thisNameRef)
|
||||||
|
|
||||||
val compositeSuperCallGenerator: () -> Unit = {
|
val compositeSuperCallGenerator: () -> Unit = {
|
||||||
val additionalStatements = mutableListOf<JsStatement>()
|
val additionalStatements = mutableListOf<JsStatement>()
|
||||||
for (partGenerator in superCallGenerators) {
|
for (partGenerator in superCallGenerators) {
|
||||||
partGenerator(additionalStatements)
|
partGenerator(additionalStatements)
|
||||||
}
|
}
|
||||||
constructorFunction.body.statements.addAll(0, additionalStatements)
|
constructorInitializer.body.statements.addAll(0, additionalStatements)
|
||||||
}
|
}
|
||||||
|
|
||||||
secondaryConstructors += ConstructorInfo(constructorFunction, context, constructorDescriptor, compositeSuperCallGenerator)
|
secondaryConstructors += ConstructorInfo(constructorInitializer, context, constructorDescriptor, compositeSuperCallGenerator)
|
||||||
secondaryConstructorProperties += constructorInitializer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val allConstructors: Sequence<ConstructorInfo>
|
private val allConstructors: Sequence<ConstructorInfo>
|
||||||
@@ -317,14 +329,9 @@ class ClassTranslator private constructor(
|
|||||||
function.body.statements.addAll(0, additionalStatements)
|
function.body.statements.addAll(0, additionalStatements)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSuperclassReferences(declarationContext: TranslationContext): JsExpression {
|
private fun addSuperclassReferences() {
|
||||||
val superClassReferences = getSupertypesNameReferences()
|
val supertypeReferences = JsArrayLiteral(getSupertypesNameReferences())
|
||||||
if (superClassReferences.isEmpty()) {
|
metadataLiteral.propertyInitializers += JsPropertyInitializer(JsNameRef(Namer.METADATA_SUPERTYPES), supertypeReferences)
|
||||||
return JsLiteral.NULL
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return simpleReturnFunction(declarationContext.scope(), JsArrayLiteral(superClassReferences))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSupertypesNameReferences(): List<JsExpression> {
|
private fun getSupertypesNameReferences(): List<JsExpression> {
|
||||||
@@ -336,7 +343,7 @@ class ClassTranslator private constructor(
|
|||||||
if (supertypes.size == 1) {
|
if (supertypes.size == 1) {
|
||||||
val type = supertypes[0]
|
val type = supertypes[0]
|
||||||
val supertypeDescriptor = getClassDescriptorForType(type)
|
val supertypeDescriptor = getClassDescriptorForType(type)
|
||||||
return listOf<JsExpression>(getClassReference(supertypeDescriptor))
|
return listOf(context().getInnerReference(supertypeDescriptor))
|
||||||
}
|
}
|
||||||
|
|
||||||
val supertypeConstructors = mutableSetOf<TypeConstructor>()
|
val supertypeConstructors = mutableSetOf<TypeConstructor>()
|
||||||
@@ -352,43 +359,111 @@ class ClassTranslator private constructor(
|
|||||||
for (typeConstructor in sortedAllSuperTypes) {
|
for (typeConstructor in sortedAllSuperTypes) {
|
||||||
if (supertypeConstructors.contains(typeConstructor)) {
|
if (supertypeConstructors.contains(typeConstructor)) {
|
||||||
val supertypeDescriptor = getClassDescriptorForTypeConstructor(typeConstructor)
|
val supertypeDescriptor = getClassDescriptorForTypeConstructor(typeConstructor)
|
||||||
supertypesRefs += getClassReference(supertypeDescriptor)
|
supertypesRefs += context().getInnerReference(supertypeDescriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return supertypesRefs
|
return supertypesRefs
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getClassReference(superClassDescriptor: ClassDescriptor): JsNameRef {
|
private fun translatePropertiesAsConstructorParameters(classDeclarationContext: TranslationContext) {
|
||||||
return context().getQualifiedReference(superClassDescriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun translatePropertiesAsConstructorParameters(classDeclarationContext: TranslationContext,
|
|
||||||
result: MutableList<JsPropertyInitializer>) {
|
|
||||||
for (parameter in getPrimaryConstructorParameters(classDeclaration)) {
|
for (parameter in getPrimaryConstructorParameters(classDeclaration)) {
|
||||||
val descriptor = getPropertyDescriptorForConstructorParameter(bindingContext(), parameter)
|
val descriptor = getPropertyDescriptorForConstructorParameter(bindingContext(), parameter)
|
||||||
if (descriptor != null) {
|
if (descriptor != null) {
|
||||||
translateAccessors(descriptor, result, classDeclarationContext)
|
val literal = JsObjectLiteral(true)
|
||||||
|
translateAccessors(descriptor, literal.propertyInitializers, classDeclarationContext)
|
||||||
|
if (literal.propertyInitializers.isNotEmpty()) {
|
||||||
|
classDeclarationContext.addAccessorsToPrototype(this.descriptor, descriptor, literal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generatedBridgeMethods(properties: MutableList<JsPropertyInitializer>) {
|
private fun addInterfaceDefaultMembers() {
|
||||||
|
val members = descriptor.unsubstitutedMemberScope
|
||||||
|
.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
|
||||||
|
.mapNotNull { it as? CallableMemberDescriptor }
|
||||||
|
for (member in members) {
|
||||||
|
if (member.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) continue
|
||||||
|
if (member.modality == Modality.ABSTRACT || member.overriddenDescriptors.size != 1) continue
|
||||||
|
|
||||||
|
val overriddenFunction = generateSequence(member) { it.overriddenDescriptors.firstOrNull() }
|
||||||
|
.drop(1)
|
||||||
|
.dropWhile { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE &&
|
||||||
|
DescriptorUtils.isInterface(it.containingDeclaration) }
|
||||||
|
.firstOrNull() ?: continue
|
||||||
|
|
||||||
|
val interfaceDescriptor = overriddenFunction.containingDeclaration as ClassDescriptor
|
||||||
|
if (interfaceDescriptor.kind != ClassKind.INTERFACE) continue
|
||||||
|
|
||||||
|
when (member) {
|
||||||
|
is FunctionDescriptor -> addDefaultMethodFromInterface(member, interfaceDescriptor)
|
||||||
|
is PropertyDescriptor -> addDefaultPropertyFromInterface(member, interfaceDescriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addDefaultMethodFromInterface(function: FunctionDescriptor, interfaceDescriptor: ClassDescriptor) {
|
||||||
|
val classPrototype = JsAstUtils.prototypeOf(context().getInnerReference(descriptor))
|
||||||
|
val interfacePrototype = JsAstUtils.prototypeOf(context().getInnerReference(interfaceDescriptor))
|
||||||
|
val functionName = context().getNameForDescriptor(function)
|
||||||
|
val classFunction = JsNameRef(functionName, classPrototype)
|
||||||
|
val interfaceFunction = JsNameRef(functionName, interfacePrototype)
|
||||||
|
context().addRootStatement(JsAstUtils.assignment(classFunction, interfaceFunction).makeStmt())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addDefaultPropertyFromInterface(property: PropertyDescriptor, interfaceDescriptor: ClassDescriptor) {
|
||||||
|
val classPrototype = JsAstUtils.prototypeOf(context().getInnerReference(descriptor))
|
||||||
|
val interfacePrototype = JsAstUtils.prototypeOf(context().getInnerReference(interfaceDescriptor))
|
||||||
|
val functionName = context().getNameForDescriptor(property)
|
||||||
|
val nameLiteral = context().program().getStringLiteral(functionName.ident)
|
||||||
|
|
||||||
|
val getPropertyDescriptor = JsInvocation(JsNameRef("getOwnPropertyDescriptor", "Object"), interfacePrototype, nameLiteral)
|
||||||
|
val defineProperty = JsAstUtils.defineProperty(classPrototype, functionName.ident, getPropertyDescriptor, context().program())
|
||||||
|
|
||||||
|
context().addRootStatement(defineProperty.makeStmt())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addObjectCache(statements: MutableList<JsStatement>) {
|
||||||
|
cachedInstanceName = context().createGlobalName(StaticContext.getSuggestedName(descriptor) + Namer.OBJECT_INSTANCE_VAR_SUFFIX)
|
||||||
|
statements += JsAstUtils.assignment(cachedInstanceName.makeRef(), JsObjectLiteral.THIS).makeStmt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addObjectMethods() {
|
||||||
|
context().addRootStatement(JsAstUtils.newVar(cachedInstanceName, JsLiteral.NULL))
|
||||||
|
|
||||||
|
val instanceFun = JsFunction(context().rootFunction.scope, JsBlock(), "Instance function: " + descriptor)
|
||||||
|
instanceFun.name = context().getNameForObjectInstance(descriptor)
|
||||||
|
|
||||||
|
val instanceCreatedCondition = JsAstUtils.equality(cachedInstanceName.makeRef(), JsLiteral.NULL)
|
||||||
|
val instanceCreationBlock = JsBlock()
|
||||||
|
val instanceCreatedGuard = JsIf(instanceCreatedCondition, instanceCreationBlock)
|
||||||
|
instanceFun.body.statements += instanceCreatedGuard
|
||||||
|
|
||||||
|
val objectRef = context().getInnerReference(descriptor)
|
||||||
|
instanceCreationBlock.statements += JsAstUtils.assignment(cachedInstanceName.makeRef(), JsNew(objectRef)).makeStmt()
|
||||||
|
|
||||||
|
instanceFun.body.statements += JsReturn(cachedInstanceName.makeRef())
|
||||||
|
|
||||||
|
context().addRootStatement(instanceFun.makeStmt())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generatedBridgeMethods() {
|
||||||
if (isAnnotation()) return
|
if (isAnnotation()) return
|
||||||
|
|
||||||
generateBridgesToTraitImpl(properties)
|
generateBridgesToTraitImpl()
|
||||||
|
|
||||||
generateOtherBridges(properties)
|
generateOtherBridges()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateBridgesToTraitImpl(properties: MutableList<JsPropertyInitializer>) {
|
private fun generateBridgesToTraitImpl() {
|
||||||
for ((key, value) in CodegenUtil.getNonPrivateTraitMethods(descriptor)) {
|
for ((key, value) in CodegenUtil.getNonPrivateTraitMethods(descriptor)) {
|
||||||
if (!areNamesEqual(key, value)) {
|
if (!areNamesEqual(key, value)) {
|
||||||
properties += generateDelegateCall(value, key, JsLiteral.THIS, context())
|
generateDelegateCall(descriptor, value, key, JsLiteral.THIS, context())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateOtherBridges(properties: MutableList<JsPropertyInitializer>) {
|
private fun generateOtherBridges() {
|
||||||
for (memberDescriptor in descriptor.defaultType.memberScope.getContributedDescriptors()) {
|
for (memberDescriptor in descriptor.defaultType.memberScope.getContributedDescriptors()) {
|
||||||
if (memberDescriptor is FunctionDescriptor) {
|
if (memberDescriptor is FunctionDescriptor) {
|
||||||
val bridgesToGenerate = generateBridgesForFunctionDescriptor(memberDescriptor, identity()) {
|
val bridgesToGenerate = generateBridgesForFunctionDescriptor(memberDescriptor, identity()) {
|
||||||
@@ -397,13 +472,13 @@ class ClassTranslator private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (bridge in bridgesToGenerate) {
|
for (bridge in bridgesToGenerate) {
|
||||||
generateBridge(bridge, properties)
|
generateBridge(bridge)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateBridge(bridge: Bridge<FunctionDescriptor>, properties: MutableList<JsPropertyInitializer>) {
|
private fun generateBridge(bridge: Bridge<FunctionDescriptor>) {
|
||||||
val fromDescriptor = bridge.from
|
val fromDescriptor = bridge.from
|
||||||
val toDescriptor = bridge.to
|
val toDescriptor = bridge.to
|
||||||
if (areNamesEqual(fromDescriptor, toDescriptor)) return
|
if (areNamesEqual(fromDescriptor, toDescriptor)) return
|
||||||
@@ -411,7 +486,7 @@ class ClassTranslator private constructor(
|
|||||||
if (fromDescriptor.kind.isReal && fromDescriptor.modality != Modality.ABSTRACT && !toDescriptor.kind.isReal)
|
if (fromDescriptor.kind.isReal && fromDescriptor.modality != Modality.ABSTRACT && !toDescriptor.kind.isReal)
|
||||||
return
|
return
|
||||||
|
|
||||||
properties += generateDelegateCall(fromDescriptor, toDescriptor, JsLiteral.THIS, context())
|
generateDelegateCall(descriptor, fromDescriptor, toDescriptor, JsLiteral.THIS, context())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun areNamesEqual(first: FunctionDescriptor, second: FunctionDescriptor): Boolean {
|
private fun areNamesEqual(first: FunctionDescriptor, second: FunctionDescriptor): Boolean {
|
||||||
@@ -421,13 +496,11 @@ class ClassTranslator private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic fun translate(classDeclaration: KtClassOrObject, context: TranslationContext): TranslationResult {
|
@JvmStatic fun translate(classDeclaration: KtClassOrObject, context: TranslationContext) {
|
||||||
return ClassTranslator(classDeclaration, context).translate()
|
return ClassTranslator(classDeclaration, context).translate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TranslationResult(val properties: List<JsPropertyInitializer>, val definitionPlace: DefinitionPlace)
|
|
||||||
|
|
||||||
private class ConstructorInfo(
|
private class ConstructorInfo(
|
||||||
val function: JsFunction,
|
val function: JsFunction,
|
||||||
val context: TranslationContext,
|
val context: TranslationContext,
|
||||||
|
|||||||
-151
@@ -1,151 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2016 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.js.translate.declaration;
|
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*;
|
|
||||||
import com.intellij.util.SmartList;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
|
||||||
import org.jetbrains.kotlin.js.translate.general.Translation;
|
|
||||||
import org.jetbrains.kotlin.js.translate.general.TranslatorVisitor;
|
|
||||||
import org.jetbrains.kotlin.js.translate.initializer.ClassInitializerTranslator;
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
|
||||||
import org.jetbrains.kotlin.psi.*;
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getClassDescriptor;
|
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getFunctionDescriptor;
|
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes;
|
|
||||||
|
|
||||||
public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
|
|
||||||
protected final List<JsPropertyInitializer> result;
|
|
||||||
private final List<JsPropertyInitializer> staticResult;
|
|
||||||
private final List<JsPropertyInitializer> enumEntryList = new SmartList<JsPropertyInitializer>();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final JsScope scope;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private List<JsStatement> initializerStatements;
|
|
||||||
|
|
||||||
public DeclarationBodyVisitor(
|
|
||||||
@NotNull List<JsPropertyInitializer> result, @NotNull List<JsPropertyInitializer> staticResult,
|
|
||||||
@NotNull JsScope scope
|
|
||||||
) {
|
|
||||||
this.result = result;
|
|
||||||
this.staticResult = staticResult;
|
|
||||||
this.scope = scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public List<JsPropertyInitializer> getResult() {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<JsPropertyInitializer> getEnumEntryList() {
|
|
||||||
return enumEntryList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Void emptyResult(@NotNull TranslationContext context) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visitClassOrObject(@NotNull KtClassOrObject declaration, TranslationContext context) {
|
|
||||||
staticResult.addAll(ClassTranslator.translate(declaration, context).getProperties());
|
|
||||||
|
|
||||||
if (declaration instanceof KtObjectDeclaration) {
|
|
||||||
KtObjectDeclaration objectDeclaration = (KtObjectDeclaration) declaration;
|
|
||||||
if (objectDeclaration.isCompanion()) {
|
|
||||||
DeclarationDescriptor descriptor = BindingUtils.getDescriptorForElement(context.bindingContext(), declaration);
|
|
||||||
addInitializerStatement(context.getQualifiedReference(descriptor).makeStmt());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visitEnumEntry(@NotNull KtEnumEntry enumEntry, TranslationContext data) {
|
|
||||||
ClassDescriptor descriptor = getClassDescriptor(data.bindingContext(), enumEntry);
|
|
||||||
List<KotlinType> supertypes = getSupertypesWithoutFakes(descriptor);
|
|
||||||
if (enumEntry.getBody() != null || supertypes.size() > 1) {
|
|
||||||
enumEntryList.addAll(ClassTranslator.translate(enumEntry, data).getProperties());
|
|
||||||
} else {
|
|
||||||
assert supertypes.size() == 1 : "Simple Enum entry must have one supertype";
|
|
||||||
JsExpression jsEnumEntryCreation = new ClassInitializerTranslator(enumEntry, data)
|
|
||||||
.generateEnumEntryInstanceCreation(supertypes.get(0));
|
|
||||||
jsEnumEntryCreation = TranslationUtils.simpleReturnFunction(data.scope(), jsEnumEntryCreation);
|
|
||||||
enumEntryList.add(new JsPropertyInitializer(data.getNameForDescriptor(descriptor).makeRef(), jsEnumEntryCreation));
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visitNamedFunction(@NotNull KtNamedFunction expression, TranslationContext context) {
|
|
||||||
FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression);
|
|
||||||
if (descriptor.getModality() == Modality.ABSTRACT) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
context = context.newDeclaration(descriptor, context.getDefinitionPlace());
|
|
||||||
JsPropertyInitializer methodAsPropertyInitializer = Translation.functionTranslator(expression, context).translateAsMethod();
|
|
||||||
result.add(methodAsPropertyInitializer);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visitProperty(@NotNull KtProperty expression, TranslationContext context) {
|
|
||||||
PropertyDescriptor propertyDescriptor = BindingUtils.getPropertyDescriptor(context.bindingContext(), expression);
|
|
||||||
context = context.newDeclaration(propertyDescriptor, context.getDefinitionPlace());
|
|
||||||
PropertyTranslatorKt.translateAccessors(propertyDescriptor, expression, result, context);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visitAnonymousInitializer(@NotNull KtAnonymousInitializer expression, TranslationContext context) {
|
|
||||||
// parsed it in initializer visitor => no additional actions are needed
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visitSecondaryConstructor(@NotNull KtSecondaryConstructor constructor, TranslationContext data) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addInitializerStatement(@NotNull JsStatement statement) {
|
|
||||||
if (initializerStatements == null) {
|
|
||||||
initializerStatements = new ArrayList<JsStatement>();
|
|
||||||
JsFunction initializerFunction = new JsFunction(scope, new JsBlock(initializerStatements), "class initializer");
|
|
||||||
staticResult.add(new JsPropertyInitializer(new JsNameRef("object_initializer$"), initializerFunction));
|
|
||||||
}
|
|
||||||
initializerStatements.add(statement);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visitTypeAlias(@NotNull KtTypeAlias typeAlias, TranslationContext data) {
|
|
||||||
// Resolved by front-end, not used by backend
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+116
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 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.js.translate.declaration
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||||
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
|
import org.jetbrains.kotlin.js.translate.initializer.ClassInitializerTranslator
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.*
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class DeclarationBodyVisitor(
|
||||||
|
private val containingClass: ClassDescriptor,
|
||||||
|
private val context: TranslationContext
|
||||||
|
) : AbstractDeclarationVisitor() {
|
||||||
|
private var enumEntryOrdinal: Int = 0
|
||||||
|
val initializerStatements = ArrayList<JsStatement>()
|
||||||
|
|
||||||
|
override fun visitClassOrObject(classOrObject: KtClassOrObject, context: TranslationContext) {
|
||||||
|
super.visitClassOrObject(classOrObject, context)
|
||||||
|
|
||||||
|
if (classOrObject is KtObjectDeclaration) {
|
||||||
|
if (classOrObject.isCompanion()) {
|
||||||
|
val descriptor = BindingUtils.getDescriptorForElement(context.bindingContext(), classOrObject) as ClassDescriptor
|
||||||
|
addInitializerStatement(JsInvocation(context.getNameForObjectInstance(descriptor).makeRef()).makeStmt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitEnumEntry(enumEntry: KtEnumEntry, context: TranslationContext) {
|
||||||
|
val descriptor = getClassDescriptor(context.bindingContext(), enumEntry)
|
||||||
|
val supertypes = getSupertypesWithoutFakes(descriptor)
|
||||||
|
|
||||||
|
if (enumEntry.getBody() != null || supertypes.size > 1) {
|
||||||
|
ClassTranslator.translate(enumEntry, context)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Simplify by omitting _getInstance() function
|
||||||
|
val enumName = context.getInnerNameForDescriptor(descriptor)
|
||||||
|
val enumInstanceName = context.createGlobalName(enumName.ident + "_instance")
|
||||||
|
|
||||||
|
assert(supertypes.size == 1) { "Simple Enum entry must have one supertype" }
|
||||||
|
val jsEnumEntryCreation = ClassInitializerTranslator
|
||||||
|
.generateEnumEntryInstanceCreation(context, supertypes[0], enumEntry, enumEntryOrdinal)
|
||||||
|
val jsEnumEntryFunction = context.createTopLevelAnonymousFunction(descriptor)
|
||||||
|
jsEnumEntryFunction.body.statements.add(JsReturn(jsEnumEntryCreation))
|
||||||
|
|
||||||
|
val enumInstanceFunction = context.createTopLevelAnonymousFunction(descriptor)
|
||||||
|
enumInstanceFunction.name = context.getNameForObjectInstance(descriptor)
|
||||||
|
context.addRootStatement(enumInstanceFunction.makeStmt())
|
||||||
|
|
||||||
|
val classRef = context.getInnerReference(descriptor.containingDeclaration)
|
||||||
|
val enumExtName = context.getNameForDescriptor(descriptor)
|
||||||
|
val enumExtFq = JsNameRef(enumExtName, classRef)
|
||||||
|
context.addRootStatement(JsAstUtils.assignment(enumExtFq, enumInstanceFunction.name.makeRef()).makeStmt())
|
||||||
|
|
||||||
|
context.addRootStatement(JsAstUtils.newVar(enumInstanceName, jsEnumEntryCreation))
|
||||||
|
enumInstanceFunction.body.statements.add(JsReturn(enumInstanceName.makeRef()))
|
||||||
|
}
|
||||||
|
|
||||||
|
enumEntryOrdinal++
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitAnonymousInitializer(expression: KtAnonymousInitializer, context: TranslationContext) {
|
||||||
|
// parsed it in initializer visitor => no additional actions are needed
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitSecondaryConstructor(constructor: KtSecondaryConstructor, data: TranslationContext) { }
|
||||||
|
|
||||||
|
private fun addInitializerStatement(statement: JsStatement) {
|
||||||
|
initializerStatements.add(statement)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addClass(descriptor: ClassDescriptor) {
|
||||||
|
//context.export(descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addFunction(descriptor: FunctionDescriptor, expression: JsExpression) {
|
||||||
|
context.addFunctionToPrototype(containingClass, descriptor, expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addProperty(descriptor: PropertyDescriptor, getter: JsExpression, setter: JsExpression?) {
|
||||||
|
if (!JsDescriptorUtils.isSimpleFinalProperty(descriptor)) {
|
||||||
|
val literal = JsObjectLiteral(true)
|
||||||
|
literal.propertyInitializers += JsPropertyInitializer(context.program().getStringLiteral("get"), getter)
|
||||||
|
if (setter != null) {
|
||||||
|
literal.propertyInitializers += JsPropertyInitializer(context.program().getStringLiteral("set"), setter)
|
||||||
|
}
|
||||||
|
context.addAccessorsToPrototype(containingClass, descriptor, literal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getBackingFieldReference(descriptor: PropertyDescriptor): JsExpression {
|
||||||
|
return Namer.getDelegateNameRef(descriptor.name.asString())
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
-16
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.translate.declaration
|
package org.jetbrains.kotlin.js.translate.declaration
|
||||||
|
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
@@ -25,15 +24,14 @@ import org.jetbrains.kotlin.js.translate.context.Namer
|
|||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
|
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.general.Translation
|
import org.jetbrains.kotlin.js.translate.general.Translation
|
||||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils
|
import org.jetbrains.kotlin.js.translate.utils.*
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.simpleReturnFunction
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.simpleReturnFunction
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateFunctionAsEcma5PropertyDescriptor
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateFunctionAsEcma5PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.js.translate.utils.generateDelegateCall
|
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
||||||
import org.jetbrains.kotlin.psi.KtSuperTypeListEntry
|
import org.jetbrains.kotlin.psi.KtSuperTypeListEntry
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty
|
||||||
|
|
||||||
class DelegationTranslator(
|
class DelegationTranslator(
|
||||||
classDeclaration: KtClassOrObject,
|
classDeclaration: KtClassOrObject,
|
||||||
@@ -53,7 +51,6 @@ class DelegationTranslator(
|
|||||||
for (specifier in delegationBySpecifiers) {
|
for (specifier in delegationBySpecifiers) {
|
||||||
val expression = specifier.delegateExpression ?:
|
val expression = specifier.delegateExpression ?:
|
||||||
throw IllegalArgumentException("delegate expression should not be null: ${specifier.text}")
|
throw IllegalArgumentException("delegate expression should not be null: ${specifier.text}")
|
||||||
val descriptor = getSuperClass(specifier)
|
|
||||||
val propertyDescriptor = CodegenUtil.getDelegatePropertyIfAny(expression, classDescriptor, bindingContext())
|
val propertyDescriptor = CodegenUtil.getDelegatePropertyIfAny(expression, classDescriptor, bindingContext())
|
||||||
|
|
||||||
if (CodegenUtil.isFinalPropertyWithBackingField(propertyDescriptor, bindingContext())) {
|
if (CodegenUtil.isFinalPropertyWithBackingField(propertyDescriptor, bindingContext())) {
|
||||||
@@ -84,22 +81,22 @@ class DelegationTranslator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateDelegated(properties: MutableList<JsPropertyInitializer>) {
|
fun generateDelegated() {
|
||||||
for (specifier in delegationBySpecifiers) {
|
for (specifier in delegationBySpecifiers) {
|
||||||
generateDelegates(getSuperClass(specifier), fields[specifier]!!, properties)
|
generateDelegates(getSuperClass(specifier), fields[specifier]!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSuperClass(specifier: KtSuperTypeListEntry): ClassDescriptor =
|
private fun getSuperClass(specifier: KtSuperTypeListEntry): ClassDescriptor =
|
||||||
CodegenUtil.getSuperClassBySuperTypeListEntry(specifier, bindingContext())
|
CodegenUtil.getSuperClassBySuperTypeListEntry(specifier, bindingContext())
|
||||||
|
|
||||||
private fun generateDelegates(toClass: ClassDescriptor, field: Field, properties: MutableList<JsPropertyInitializer>) {
|
private fun generateDelegates(toClass: ClassDescriptor, field: Field) {
|
||||||
for ((descriptor, overriddenDescriptor) in CodegenUtil.getDelegates(classDescriptor, toClass)) {
|
for ((descriptor, overriddenDescriptor) in CodegenUtil.getDelegates(classDescriptor, toClass)) {
|
||||||
when (descriptor) {
|
when (descriptor) {
|
||||||
is PropertyDescriptor ->
|
is PropertyDescriptor ->
|
||||||
generateDelegateCallForPropertyMember(descriptor, field.name, properties)
|
generateDelegateCallForPropertyMember(descriptor, field.name)
|
||||||
is FunctionDescriptor ->
|
is FunctionDescriptor ->
|
||||||
generateDelegateCallForFunctionMember(descriptor, overriddenDescriptor as FunctionDescriptor, field.name, properties)
|
generateDelegateCallForFunctionMember(descriptor, overriddenDescriptor as FunctionDescriptor, field.name)
|
||||||
else ->
|
else ->
|
||||||
throw IllegalArgumentException("Expected property or function $descriptor")
|
throw IllegalArgumentException("Expected property or function $descriptor")
|
||||||
}
|
}
|
||||||
@@ -108,8 +105,7 @@ class DelegationTranslator(
|
|||||||
|
|
||||||
private fun generateDelegateCallForPropertyMember(
|
private fun generateDelegateCallForPropertyMember(
|
||||||
descriptor: PropertyDescriptor,
|
descriptor: PropertyDescriptor,
|
||||||
delegateName: JsName,
|
delegateName: JsName
|
||||||
properties: MutableList<JsPropertyInitializer>
|
|
||||||
) {
|
) {
|
||||||
val propertyName: String = descriptor.name.asString()
|
val propertyName: String = descriptor.name.asString()
|
||||||
|
|
||||||
@@ -174,17 +170,29 @@ class DelegationTranslator(
|
|||||||
return generateDelegateAccessor(setterDescriptor, generateDelegateSetterFunction(setterDescriptor))
|
return generateDelegateAccessor(setterDescriptor, generateDelegateSetterFunction(setterDescriptor))
|
||||||
}
|
}
|
||||||
|
|
||||||
properties.addGetterAndSetter(descriptor, context(), ::generateDelegateGetter, ::generateDelegateSetter)
|
// TODO: same logic as in AbstractDeclarationVisitor
|
||||||
|
if (descriptor.isExtensionProperty || TranslationUtils.shouldAccessViaFunctions(descriptor)) {
|
||||||
|
val getter = descriptor.getter!!
|
||||||
|
context().addFunctionToPrototype(classDescriptor, getter, generateDelegateGetterFunction(getter))
|
||||||
|
if (descriptor.isVar) {
|
||||||
|
val setter = descriptor.setter!!
|
||||||
|
context().addFunctionToPrototype(classDescriptor, setter, generateDelegateSetterFunction(setter))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val literal = JsObjectLiteral(true)
|
||||||
|
literal.propertyInitializers.addGetterAndSetter(descriptor, ::generateDelegateGetter, ::generateDelegateSetter)
|
||||||
|
context().addAccessorsToPrototype(classDescriptor, descriptor, literal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun generateDelegateCallForFunctionMember(
|
private fun generateDelegateCallForFunctionMember(
|
||||||
descriptor: FunctionDescriptor,
|
descriptor: FunctionDescriptor,
|
||||||
overriddenDescriptor: FunctionDescriptor,
|
overriddenDescriptor: FunctionDescriptor,
|
||||||
delegateName: JsName,
|
delegateName: JsName
|
||||||
properties: MutableList<JsPropertyInitializer>
|
|
||||||
) {
|
) {
|
||||||
val delegateRef = JsNameRef(delegateName, JsLiteral.THIS)
|
val delegateRef = JsNameRef(delegateName, JsLiteral.THIS)
|
||||||
properties.add(generateDelegateCall(descriptor, overriddenDescriptor, delegateRef, context()))
|
generateDelegateCall(classDescriptor, descriptor, overriddenDescriptor, delegateRef, context())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2016 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.js.translate.declaration
|
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsFunction
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsScope
|
|
||||||
import com.intellij.util.SmartList
|
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
|
||||||
import org.jetbrains.kotlin.js.translate.general.Translation
|
|
||||||
import org.jetbrains.kotlin.js.translate.initializer.InitializerUtils.generateInitializerForDelegate
|
|
||||||
import org.jetbrains.kotlin.js.translate.initializer.InitializerUtils.generateInitializerForProperty
|
|
||||||
import org.jetbrains.kotlin.js.translate.initializer.InitializerVisitor
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getPropertyDescriptor
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
|
||||||
import org.jetbrains.kotlin.psi.*
|
|
||||||
|
|
||||||
class FileDeclarationVisitor(
|
|
||||||
val context: TranslationContext,
|
|
||||||
scope: JsScope,
|
|
||||||
initializers: List<JsPropertyInitializer> = SmartList()
|
|
||||||
) : DeclarationBodyVisitor(initializers, SmartList(), scope) {
|
|
||||||
|
|
||||||
private val initializer = JsAstUtils.createFunctionWithEmptyBody(context.scope())
|
|
||||||
private val initializerContext = context.contextWithScope(initializer).innerBlock(initializer.body)
|
|
||||||
private val initializerVisitor = InitializerVisitor()
|
|
||||||
|
|
||||||
fun computeInitializer(): JsFunction? {
|
|
||||||
return if (initializer.body.statements.isNotEmpty()) initializer else null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitClassOrObject(declaration: KtClassOrObject, context: TranslationContext?): Void? {
|
|
||||||
result += ClassTranslator.translate(declaration, context!!).properties
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitProperty(expression: KtProperty, context: TranslationContext?): Void? {
|
|
||||||
context!! // hack
|
|
||||||
|
|
||||||
super.visitProperty(expression, context)
|
|
||||||
val initializer = expression.initializer
|
|
||||||
if (initializer != null) {
|
|
||||||
val value = Translation.translateAsExpression(initializer, initializerContext)
|
|
||||||
val propertyDescriptor: PropertyDescriptor = getPropertyDescriptor(context.bindingContext(), expression)
|
|
||||||
this.initializer.body.statements += generateInitializerForProperty(context, propertyDescriptor, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
generateInitializerForDelegate(context, expression)?.let { this.initializer.body.statements += it }
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitAnonymousInitializer(expression: KtAnonymousInitializer, context: TranslationContext?): Void? {
|
|
||||||
expression.accept(initializerVisitor, initializerContext)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+82
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 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.js.translate.declaration
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsExpression
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsFunction
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsName
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
|
import org.jetbrains.kotlin.js.translate.general.Translation
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.BindingUtils
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.psi.KtProperty
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
|
||||||
|
class FileDeclarationVisitor(private val context: TranslationContext) : AbstractDeclarationVisitor() {
|
||||||
|
override fun visitProperty(expression: KtProperty, context: TranslationContext) {
|
||||||
|
val propertyDescriptor = BindingUtils.getPropertyDescriptor(context.bindingContext(), expression)
|
||||||
|
|
||||||
|
val innerName = context.getInnerNameForDescriptor(propertyDescriptor)
|
||||||
|
val backingFieldRequired = context.bindingContext()[BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor] ?: false
|
||||||
|
if (backingFieldRequired || expression.delegateExpression != null) {
|
||||||
|
val initializer = expression.delegateExpressionOrInitializer?.let { Translation.translateAsExpression(it, context) }
|
||||||
|
context.addRootStatement(JsAstUtils.newVar(innerName, initializer))
|
||||||
|
}
|
||||||
|
|
||||||
|
super.visitProperty(expression, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addClass(descriptor: ClassDescriptor) {
|
||||||
|
context.export(descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addFunction(descriptor: FunctionDescriptor, expression: JsExpression) {
|
||||||
|
addFunctionButNotExport(descriptor, expression)
|
||||||
|
context.export(descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addProperty(descriptor: PropertyDescriptor, getter: JsExpression, setter: JsExpression?) {
|
||||||
|
if (!JsDescriptorUtils.isSimpleFinalProperty(descriptor)) {
|
||||||
|
addFunctionButNotExport(descriptor.getter!!, getter)
|
||||||
|
if (setter != null) {
|
||||||
|
addFunctionButNotExport(descriptor.setter!!, setter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.export(descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getBackingFieldReference(descriptor: PropertyDescriptor): JsExpression {
|
||||||
|
return context.getInnerReference(descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addFunctionButNotExport(descriptor: FunctionDescriptor, expression: JsExpression): JsName {
|
||||||
|
val name = context.getInnerNameForDescriptor(descriptor)
|
||||||
|
when (expression) {
|
||||||
|
is JsFunction -> {
|
||||||
|
expression.name = name
|
||||||
|
context.addRootStatement(expression.makeStmt())
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
context.addRootStatement(JsAstUtils.newVar(name, expression))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-9
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.*;
|
|||||||
import org.jetbrains.kotlin.js.translate.context.Namer;
|
import org.jetbrains.kotlin.js.translate.context.Namer;
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.UtilsKt;
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||||
import org.jetbrains.kotlin.psi.KtParameter;
|
import org.jetbrains.kotlin.psi.KtParameter;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
@@ -37,12 +38,10 @@ import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.or;
|
|||||||
|
|
||||||
class JsDataClassGenerator extends DataClassMethodGenerator {
|
class JsDataClassGenerator extends DataClassMethodGenerator {
|
||||||
private final TranslationContext context;
|
private final TranslationContext context;
|
||||||
private final List<? super JsPropertyInitializer> output;
|
|
||||||
|
|
||||||
JsDataClassGenerator(KtClassOrObject klass, TranslationContext context, List<? super JsPropertyInitializer> output) {
|
JsDataClassGenerator(KtClassOrObject klass, TranslationContext context) {
|
||||||
super(klass, context.bindingContext());
|
super(klass, context.bindingContext());
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.output = output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -94,7 +93,7 @@ class JsDataClassGenerator extends DataClassMethodGenerator {
|
|||||||
ClassDescriptor classDescriptor = (ClassDescriptor) function.getContainingDeclaration();
|
ClassDescriptor classDescriptor = (ClassDescriptor) function.getContainingDeclaration();
|
||||||
ClassConstructorDescriptor constructor = classDescriptor.getConstructors().iterator().next();
|
ClassConstructorDescriptor constructor = classDescriptor.getConstructors().iterator().next();
|
||||||
|
|
||||||
JsExpression constructorRef = context.getQualifiedReference(constructor);
|
JsExpression constructorRef = context.getInnerReference(constructor);
|
||||||
|
|
||||||
JsExpression returnExpression = new JsNew(constructorRef, constructorArguments);
|
JsExpression returnExpression = new JsNew(constructorRef, constructorArguments);
|
||||||
if (context.shouldBeDeferred(constructor)) {
|
if (context.shouldBeDeferred(constructor)) {
|
||||||
@@ -190,11 +189,9 @@ class JsDataClassGenerator extends DataClassMethodGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private JsFunction generateJsMethod(@NotNull FunctionDescriptor functionDescriptor) {
|
private JsFunction generateJsMethod(@NotNull FunctionDescriptor functionDescriptor) {
|
||||||
JsName functionName = context.getNameForDescriptor(functionDescriptor);
|
JsFunction functionObject = context.createTopLevelAnonymousFunction(functionDescriptor);
|
||||||
JsScope enclosingScope = context.scope();
|
ClassDescriptor containingClass = (ClassDescriptor) functionDescriptor.getContainingDeclaration();
|
||||||
JsFunction functionObject = JsAstUtils.createFunctionWithEmptyBody(enclosingScope);
|
UtilsKt.addFunctionToPrototype(context, containingClass, functionDescriptor, functionObject);
|
||||||
JsPropertyInitializer initializer = new JsPropertyInitializer(functionName.makeRef(), functionObject);
|
|
||||||
output.add(initializer);
|
|
||||||
return functionObject;
|
return functionObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-43
@@ -16,30 +16,22 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.translate.declaration;
|
package org.jetbrains.kotlin.js.translate.declaration;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*;
|
|
||||||
import gnu.trove.THashMap;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
|
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
|
||||||
import org.jetbrains.kotlin.js.facade.exceptions.TranslationRuntimeException;
|
import org.jetbrains.kotlin.js.facade.exceptions.TranslationRuntimeException;
|
||||||
import org.jetbrains.kotlin.js.translate.context.Namer;
|
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Collection;
|
||||||
|
|
||||||
import static com.google.dart.compiler.backend.js.ast.JsVars.JsVar;
|
|
||||||
|
|
||||||
public final class PackageDeclarationTranslator extends AbstractTranslator {
|
public final class PackageDeclarationTranslator extends AbstractTranslator {
|
||||||
private final Iterable<KtFile> files;
|
private final Iterable<KtFile> files;
|
||||||
private final Map<PackageFragmentDescriptor, PackageTranslator> packageFragmentToTranslator =
|
|
||||||
new LinkedHashMap<PackageFragmentDescriptor, PackageTranslator>();
|
|
||||||
|
|
||||||
public static List<JsStatement> translateFiles(@NotNull Collection<KtFile> files, @NotNull TranslationContext context) {
|
public static void translateFiles(@NotNull Collection<KtFile> files, @NotNull TranslationContext context) {
|
||||||
return new PackageDeclarationTranslator(files, context).translate();
|
new PackageDeclarationTranslator(files, context).translate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private PackageDeclarationTranslator(@NotNull Iterable<KtFile> files, @NotNull TranslationContext context) {
|
private PackageDeclarationTranslator(@NotNull Iterable<KtFile> files, @NotNull TranslationContext context) {
|
||||||
@@ -48,21 +40,12 @@ public final class PackageDeclarationTranslator extends AbstractTranslator {
|
|||||||
this.files = files;
|
this.files = files;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
private void translate() {
|
||||||
private List<JsStatement> translate() {
|
|
||||||
// predictable order
|
|
||||||
Map<FqName, DefineInvocation> packageFqNameToDefineInvocation = new THashMap<FqName, DefineInvocation>();
|
|
||||||
|
|
||||||
for (KtFile file : files) {
|
for (KtFile file : files) {
|
||||||
PackageFragmentDescriptor packageFragment =
|
PackageFragmentDescriptor packageFragment =
|
||||||
BindingContextUtils.getNotNull(context().bindingContext(), BindingContext.FILE_TO_PACKAGE_FRAGMENT, file);
|
BindingContextUtils.getNotNull(context().bindingContext(), BindingContext.FILE_TO_PACKAGE_FRAGMENT, file);
|
||||||
|
|
||||||
PackageTranslator translator = packageFragmentToTranslator.get(packageFragment);
|
PackageTranslator translator = PackageTranslator.create(packageFragment, context());
|
||||||
if (translator == null) {
|
|
||||||
createRootPackageDefineInvocationIfNeeded(packageFqNameToDefineInvocation);
|
|
||||||
translator = PackageTranslator.create(packageFragment, context());
|
|
||||||
packageFragmentToTranslator.put(packageFragment, translator);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
translator.translate(file);
|
translator.translate(file);
|
||||||
@@ -77,26 +60,5 @@ public final class PackageDeclarationTranslator extends AbstractTranslator {
|
|||||||
throw new TranslationRuntimeException(file, e);
|
throw new TranslationRuntimeException(file, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PackageTranslator translator : packageFragmentToTranslator.values()) {
|
|
||||||
translator.add(packageFqNameToDefineInvocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
JsVars vars = new JsVars(true);
|
|
||||||
vars.addIfHasInitializer(getRootPackageDeclaration(packageFqNameToDefineInvocation.get(FqName.ROOT)));
|
|
||||||
|
|
||||||
return Collections.<JsStatement>singletonList(vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createRootPackageDefineInvocationIfNeeded(@NotNull Map<FqName, DefineInvocation> packageFqNameToDefineInvocation) {
|
|
||||||
if (!packageFqNameToDefineInvocation.containsKey(FqName.ROOT)) {
|
|
||||||
packageFqNameToDefineInvocation.put(
|
|
||||||
FqName.ROOT, DefineInvocation.create(FqName.ROOT, null, new JsObjectLiteral(true), context()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private JsVar getRootPackageDeclaration(@NotNull DefineInvocation defineInvocation) {
|
|
||||||
JsExpression rootPackageVar = new JsInvocation(context().namer().rootPackageDefinitionMethodReference(), defineInvocation.asList());
|
|
||||||
return new JsVar(context().scope().declareName(Namer.getRootPackageName()), rootPackageVar);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-87
@@ -16,51 +16,32 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.translate.declaration;
|
package org.jetbrains.kotlin.js.translate.declaration;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*;
|
|
||||||
import com.intellij.util.SmartList;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
|
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
|
||||||
import org.jetbrains.kotlin.js.translate.context.DefinitionPlace;
|
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils;
|
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
|
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration;
|
import org.jetbrains.kotlin.psi.KtDeclaration;
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
final class PackageTranslator extends AbstractTranslator {
|
final class PackageTranslator extends AbstractTranslator {
|
||||||
static PackageTranslator create(
|
static PackageTranslator create(
|
||||||
@NotNull PackageFragmentDescriptor descriptor,
|
@NotNull PackageFragmentDescriptor descriptor,
|
||||||
@NotNull TranslationContext context
|
@NotNull TranslationContext context
|
||||||
) {
|
) {
|
||||||
JsScope scope = context.getScopeForDescriptor(descriptor);
|
TranslationContext newContext = context.newDeclaration(descriptor);
|
||||||
JsNameRef reference = context.getQualifiedReference(descriptor);
|
FileDeclarationVisitor visitor = new FileDeclarationVisitor(newContext);
|
||||||
SmartList<JsPropertyInitializer> properties = new SmartList<JsPropertyInitializer>();
|
return new PackageTranslator(newContext, visitor);
|
||||||
|
|
||||||
DefinitionPlace definitionPlace = new DefinitionPlace((JsObjectScope) scope, reference, properties);
|
|
||||||
|
|
||||||
TranslationContext newContext = context.newDeclaration(descriptor, definitionPlace);
|
|
||||||
FileDeclarationVisitor visitor = new FileDeclarationVisitor(newContext, scope, definitionPlace.getProperties());
|
|
||||||
return new PackageTranslator(descriptor, newContext, visitor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final PackageFragmentDescriptor descriptor;
|
|
||||||
|
|
||||||
private final FileDeclarationVisitor visitor;
|
private final FileDeclarationVisitor visitor;
|
||||||
|
|
||||||
private PackageTranslator(
|
private PackageTranslator(
|
||||||
@NotNull PackageFragmentDescriptor descriptor,
|
|
||||||
@NotNull TranslationContext context,
|
@NotNull TranslationContext context,
|
||||||
@NotNull FileDeclarationVisitor visitor
|
@NotNull FileDeclarationVisitor visitor
|
||||||
) {
|
) {
|
||||||
super(context);
|
super(context);
|
||||||
this.descriptor = descriptor;
|
|
||||||
this.visitor = visitor;
|
this.visitor = visitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,69 +52,4 @@ final class PackageTranslator extends AbstractTranslator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createDefinitionPlace(
|
|
||||||
@Nullable JsExpression initializer,
|
|
||||||
Map<FqName, DefineInvocation> packageFqNameToDefineInvocation
|
|
||||||
) {
|
|
||||||
FqName fqName = descriptor.getFqName();
|
|
||||||
DefineInvocation place = DefineInvocation.create(fqName, initializer, new JsObjectLiteral(visitor.getResult(), true), context());
|
|
||||||
packageFqNameToDefineInvocation.put(fqName, place);
|
|
||||||
addToParent(fqName.parent(), getEntry(fqName, place), packageFqNameToDefineInvocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(@NotNull Map<FqName, DefineInvocation> packageFqNameToDefineInvocation) {
|
|
||||||
JsExpression initializer = visitor.computeInitializer();
|
|
||||||
|
|
||||||
DefineInvocation defineInvocation = packageFqNameToDefineInvocation.get(descriptor.getFqName());
|
|
||||||
if (defineInvocation == null) {
|
|
||||||
if (initializer != null || !visitor.getResult().isEmpty()) {
|
|
||||||
createDefinitionPlace(initializer, packageFqNameToDefineInvocation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (initializer != null) {
|
|
||||||
assert defineInvocation.getInitializer() == JsLiteral.NULL;
|
|
||||||
defineInvocation.setInitializer(initializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<JsPropertyInitializer> listFromPlace = defineInvocation.getMembers();
|
|
||||||
// if equals, so, inner functions was added
|
|
||||||
if (listFromPlace != visitor.getResult()) {
|
|
||||||
listFromPlace.addAll(visitor.getResult());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private JsPropertyInitializer getEntry(@NotNull FqName fqName, DefineInvocation defineInvocation) {
|
|
||||||
return new JsPropertyInitializer(context().getNameForPackage(fqName).makeRef(),
|
|
||||||
new JsInvocation(context().namer().packageDefinitionMethodReference(), defineInvocation.asList()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean addEntryIfParentExists(
|
|
||||||
FqName parentFqName,
|
|
||||||
JsPropertyInitializer entry,
|
|
||||||
Map<FqName, DefineInvocation> packageFqNameToDeclarationPlace
|
|
||||||
) {
|
|
||||||
DefineInvocation parentDefineInvocation = packageFqNameToDeclarationPlace.get(parentFqName);
|
|
||||||
if (parentDefineInvocation != null) {
|
|
||||||
parentDefineInvocation.getMembers().add(entry);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addToParent(@NotNull FqName parentFqName,
|
|
||||||
JsPropertyInitializer entry,
|
|
||||||
Map<FqName, DefineInvocation> packageFqNameToDefineInvocation) {
|
|
||||||
while (!addEntryIfParentExists(parentFqName, entry, packageFqNameToDefineInvocation)) {
|
|
||||||
JsObjectLiteral members = new JsObjectLiteral(new SmartList<JsPropertyInitializer>(entry), true);
|
|
||||||
DefineInvocation defineInvocation = DefineInvocation.create(parentFqName, null, members, context());
|
|
||||||
entry = getEntry(parentFqName, defineInvocation);
|
|
||||||
|
|
||||||
packageFqNameToDefineInvocation.put(parentFqName, defineInvocation);
|
|
||||||
parentFqName = parentFqName.parent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+88
-96
@@ -17,7 +17,6 @@
|
|||||||
package org.jetbrains.kotlin.js.translate.declaration
|
package org.jetbrains.kotlin.js.translate.declaration
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
import com.intellij.util.SmartList
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableAccessorDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.LocalVariableAccessorDescriptor
|
||||||
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator
|
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator
|
||||||
@@ -27,12 +26,10 @@ import org.jetbrains.kotlin.js.translate.context.Namer.getReceiverParameterName
|
|||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
|
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.general.Translation
|
import org.jetbrains.kotlin.js.translate.general.Translation
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.BindingUtils
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.*
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.assignmentToBackingField
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.backingFieldReference
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateFunctionAsEcma5PropertyDescriptor
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.addParameter
|
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.addParameter
|
||||||
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.addStatement
|
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.addStatement
|
||||||
import org.jetbrains.kotlin.psi.KtProperty
|
import org.jetbrains.kotlin.psi.KtProperty
|
||||||
@@ -68,87 +65,40 @@ fun translateAccessors(
|
|||||||
|
|
||||||
fun MutableList<JsPropertyInitializer>.addGetterAndSetter(
|
fun MutableList<JsPropertyInitializer>.addGetterAndSetter(
|
||||||
descriptor: VariableDescriptorWithAccessors,
|
descriptor: VariableDescriptorWithAccessors,
|
||||||
context: TranslationContext,
|
|
||||||
generateGetter: () -> JsPropertyInitializer,
|
generateGetter: () -> JsPropertyInitializer,
|
||||||
generateSetter: () -> JsPropertyInitializer
|
generateSetter: () -> JsPropertyInitializer
|
||||||
) {
|
) {
|
||||||
val to: MutableList<JsPropertyInitializer>
|
add(generateGetter())
|
||||||
if (!descriptor.isExtension && !TranslationUtils.shouldGenerateAccessors(descriptor)) {
|
|
||||||
to = SmartList<JsPropertyInitializer>()
|
|
||||||
this.add(JsPropertyInitializer(context.getNameForDescriptor(descriptor).makeRef(), JsObjectLiteral(to, true)))
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
to = this
|
|
||||||
}
|
|
||||||
|
|
||||||
to.add(generateGetter())
|
|
||||||
if (descriptor.isVar) {
|
if (descriptor.isVar) {
|
||||||
to.add(generateSetter())
|
add(generateSetter())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PropertyTranslator(
|
class DefaultPropertyTranslator(
|
||||||
val descriptor: VariableDescriptorWithAccessors,
|
val descriptor: VariableDescriptorWithAccessors,
|
||||||
val declaration: KtProperty?,
|
context: TranslationContext,
|
||||||
context: TranslationContext
|
val delegateReference: JsExpression
|
||||||
) : AbstractTranslator(context) {
|
) : AbstractTranslator(context) {
|
||||||
|
fun generateDefaultGetterFunction(getterDescriptor: VariableAccessorDescriptor, function: JsFunction) {
|
||||||
private val propertyName: String = descriptor.name.asString()
|
val delegatedCall = bindingContext()[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor]
|
||||||
|
|
||||||
fun translate(result: MutableList<JsPropertyInitializer>) {
|
|
||||||
result.addGetterAndSetter(descriptor, context(), { generateGetter() }, { generateSetter() })
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateGetter(): JsPropertyInitializer =
|
|
||||||
if (hasCustomGetter()) translateCustomAccessor(getCustomGetterDeclaration()) else generateDefaultGetter()
|
|
||||||
|
|
||||||
private fun generateSetter(): JsPropertyInitializer =
|
|
||||||
if (hasCustomSetter()) translateCustomAccessor(getCustomSetterDeclaration()) else generateDefaultSetter()
|
|
||||||
|
|
||||||
private fun hasCustomGetter() = declaration?.getter != null && getCustomGetterDeclaration().hasBody()
|
|
||||||
|
|
||||||
private fun hasCustomSetter() = declaration?.setter != null && getCustomSetterDeclaration().hasBody()
|
|
||||||
|
|
||||||
private fun getCustomGetterDeclaration(): KtPropertyAccessor =
|
|
||||||
declaration?.getter ?:
|
|
||||||
throw IllegalStateException("declaration and getter should not be null descriptor=$descriptor declaration=$declaration")
|
|
||||||
|
|
||||||
private fun getCustomSetterDeclaration(): KtPropertyAccessor =
|
|
||||||
declaration?.setter ?:
|
|
||||||
throw IllegalStateException("declaration and setter should not be null descriptor=$descriptor declaration=$declaration")
|
|
||||||
|
|
||||||
private fun generateDefaultGetter(): JsPropertyInitializer {
|
|
||||||
val getterDescriptor = descriptor.getter ?: throw IllegalStateException("Getter descriptor should not be null")
|
|
||||||
return generateDefaultAccessor(getterDescriptor, generateDefaultGetterFunction(getterDescriptor))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateDefaultGetterFunction(getterDescriptor: VariableAccessorDescriptor): JsFunction {
|
|
||||||
val delegatedCall = bindingContext().get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor)
|
|
||||||
|
|
||||||
if (delegatedCall != null) {
|
if (delegatedCall != null) {
|
||||||
return generateDelegatedGetterFunction(getterDescriptor, delegatedCall)
|
return generateDelegatedGetterFunction(getterDescriptor, delegatedCall, function)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!descriptor.isExtension) { "Unexpected extension property $descriptor}" }
|
assert(!descriptor.isExtension) { "Unexpected extension property $descriptor}" }
|
||||||
assert(descriptor is PropertyDescriptor) { "Property descriptor expected: $descriptor" }
|
assert(descriptor is PropertyDescriptor) { "Property descriptor expected: $descriptor" }
|
||||||
val scope = context().getScopeForDescriptor(getterDescriptor.containingDeclaration)
|
|
||||||
val result = backingFieldReference(context(), descriptor as PropertyDescriptor)
|
val result = backingFieldReference(context(), descriptor as PropertyDescriptor)
|
||||||
val body = JsBlock(JsReturn(result))
|
function.body.statements += JsReturn(result)
|
||||||
|
|
||||||
return JsFunction(scope, body, accessorDescription(getterDescriptor))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateDelegatedGetterFunction(
|
private fun generateDelegatedGetterFunction(
|
||||||
getterDescriptor: VariableAccessorDescriptor,
|
getterDescriptor: VariableAccessorDescriptor,
|
||||||
delegatedCall: ResolvedCall<FunctionDescriptor>
|
delegatedCall: ResolvedCall<FunctionDescriptor>,
|
||||||
): JsFunction {
|
function: JsFunction
|
||||||
val scope = context().getScopeForDescriptor(getterDescriptor.containingDeclaration)
|
) {
|
||||||
val function = JsFunction(scope, JsBlock(), accessorDescription(getterDescriptor))
|
val delegateContext = contextWithPropertyMetadataCreationIntrinsified(context(), delegatedCall, getterDescriptor)
|
||||||
|
val delegatedJsCall = CallTranslator.translate(delegateContext, delegatedCall, delegateReference)
|
||||||
val delegateRef = getDelegateNameRef(propertyName)
|
|
||||||
val delegatedJsCall = CallTranslator.translate(
|
|
||||||
contextWithPropertyMetadataCreationIntrinsified(context(), delegatedCall, getterDescriptor), delegatedCall, delegateRef
|
|
||||||
)
|
|
||||||
|
|
||||||
if (getterDescriptor.isExtension) {
|
if (getterDescriptor.isExtension) {
|
||||||
val receiver = function.addParameter(getReceiverParameterName()).name
|
val receiver = function.addParameter(getReceiverParameterName()).name
|
||||||
@@ -158,40 +108,18 @@ private class PropertyTranslator(
|
|||||||
|
|
||||||
val returnResult = JsReturn(delegatedJsCall)
|
val returnResult = JsReturn(delegatedJsCall)
|
||||||
function.addStatement(returnResult)
|
function.addStatement(returnResult)
|
||||||
return function
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun contextWithPropertyMetadataCreationIntrinsified(
|
fun generateDefaultSetterFunction(setterDescriptor: VariableAccessorDescriptor, function: JsFunction) {
|
||||||
context: TranslationContext, delegatedCall: ResolvedCall<FunctionDescriptor>, accessor: VariableAccessorDescriptor
|
|
||||||
): TranslationContext {
|
|
||||||
val propertyNameLiteral = context.program().getStringLiteral(accessor.correspondingVariable.name.asString())
|
|
||||||
// 0th argument is instance, 1st is KProperty, 2nd (for setter) is value
|
|
||||||
val fakeArgumentExpression =
|
|
||||||
(delegatedCall.valueArgumentsByIndex!![1] as ExpressionValueArgument).valueArgument!!.getArgumentExpression()
|
|
||||||
return context.innerContextWithAliasesForExpressions(mapOf(
|
|
||||||
fakeArgumentExpression to JsNew(pureFqn("PropertyMetadata", Namer.kotlinObject()), listOf(propertyNameLiteral))
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateDefaultSetter(): JsPropertyInitializer {
|
|
||||||
val setterDescriptor = descriptor.setter ?: throw IllegalStateException("Setter descriptor should not be null")
|
|
||||||
return generateDefaultAccessor(setterDescriptor, generateDefaultSetterFunction(setterDescriptor))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateDefaultSetterFunction(setterDescriptor: VariableAccessorDescriptor): JsFunction {
|
|
||||||
val function = JsFunction(context().program().rootScope, JsBlock(), accessorDescription(setterDescriptor))
|
|
||||||
|
|
||||||
assert(setterDescriptor.valueParameters.size == 1) { "Setter must have 1 parameter" }
|
assert(setterDescriptor.valueParameters.size == 1) { "Setter must have 1 parameter" }
|
||||||
val correspondingPropertyName = setterDescriptor.correspondingVariable.name.asString()
|
val correspondingPropertyName = setterDescriptor.correspondingVariable.name.asString()
|
||||||
val valueParameter = function.addParameter(correspondingPropertyName).name
|
val valueParameter = function.addParameter(correspondingPropertyName).name
|
||||||
val withAliased = context().innerContextWithAliased(setterDescriptor.valueParameters[0], valueParameter.makeRef())
|
val withAliased = context().innerContextWithAliased(setterDescriptor.valueParameters[0], valueParameter.makeRef())
|
||||||
val delegatedCall = context().bindingContext().get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, setterDescriptor)
|
val delegatedCall = bindingContext()[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, setterDescriptor]
|
||||||
|
|
||||||
if (delegatedCall != null) {
|
if (delegatedCall != null) {
|
||||||
val delegatedJsCall = CallTranslator.translate(
|
val delegateContext = contextWithPropertyMetadataCreationIntrinsified(withAliased, delegatedCall, setterDescriptor)
|
||||||
contextWithPropertyMetadataCreationIntrinsified(withAliased, delegatedCall, setterDescriptor),
|
val delegatedJsCall = CallTranslator.translate(delegateContext, delegatedCall, delegateReference)
|
||||||
delegatedCall, getDelegateNameRef(correspondingPropertyName)
|
|
||||||
)
|
|
||||||
function.addStatement(delegatedJsCall.makeStmt())
|
function.addStatement(delegatedJsCall.makeStmt())
|
||||||
|
|
||||||
if (setterDescriptor.isExtension) {
|
if (setterDescriptor.isExtension) {
|
||||||
@@ -205,15 +133,79 @@ private class PropertyTranslator(
|
|||||||
val assignment = assignmentToBackingField(withAliased, descriptor as PropertyDescriptor, valueParameter.makeRef())
|
val assignment = assignmentToBackingField(withAliased, descriptor as PropertyDescriptor, valueParameter.makeRef())
|
||||||
function.addStatement(assignment.makeStmt())
|
function.addStatement(assignment.makeStmt())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return function
|
private fun contextWithPropertyMetadataCreationIntrinsified(
|
||||||
|
context: TranslationContext, delegatedCall: ResolvedCall<FunctionDescriptor>, accessor: VariableAccessorDescriptor
|
||||||
|
): TranslationContext {
|
||||||
|
val propertyNameLiteral = context.program().getStringLiteral(accessor.correspondingVariable.name.asString())
|
||||||
|
// 0th argument is instance, 1st is KProperty, 2nd (for setter) is value
|
||||||
|
val fakeArgumentExpression =
|
||||||
|
(delegatedCall.valueArgumentsByIndex!![1] as ExpressionValueArgument).valueArgument!!.getArgumentExpression()
|
||||||
|
return context.innerContextWithAliasesForExpressions(mapOf(
|
||||||
|
fakeArgumentExpression to JsNew(pureFqn("PropertyMetadata", Namer.kotlinObject()), listOf(propertyNameLiteral))
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun KtProperty.hasCustomGetter() = getter?.hasBody() ?: false
|
||||||
|
|
||||||
|
fun KtProperty.hasCustomSetter() = setter?.hasBody() ?: false
|
||||||
|
|
||||||
|
private class PropertyTranslator(
|
||||||
|
val descriptor: VariableDescriptorWithAccessors,
|
||||||
|
val declaration: KtProperty?,
|
||||||
|
context: TranslationContext
|
||||||
|
) : AbstractTranslator(context) {
|
||||||
|
|
||||||
|
fun translate(result: MutableList<JsPropertyInitializer>) {
|
||||||
|
result.addGetterAndSetter(descriptor, { generateGetter() }, { generateSetter() })
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateGetter(): JsPropertyInitializer =
|
||||||
|
if (declaration?.hasCustomGetter() ?: false) translateCustomAccessor(getCustomGetterDeclaration()) else generateDefaultGetter()
|
||||||
|
|
||||||
|
private fun generateSetter(): JsPropertyInitializer =
|
||||||
|
if (declaration?.hasCustomSetter() ?: false) translateCustomAccessor(getCustomSetterDeclaration()) else generateDefaultSetter()
|
||||||
|
|
||||||
|
private fun getCustomGetterDeclaration(): KtPropertyAccessor =
|
||||||
|
declaration?.getter ?:
|
||||||
|
throw IllegalStateException("declaration and getter should not be null descriptor=$descriptor declaration=$declaration")
|
||||||
|
|
||||||
|
private fun getCustomSetterDeclaration(): KtPropertyAccessor =
|
||||||
|
declaration?.setter ?:
|
||||||
|
throw IllegalStateException("declaration and setter should not be null descriptor=$descriptor declaration=$declaration")
|
||||||
|
|
||||||
|
private fun generateDefaultGetter(): JsPropertyInitializer {
|
||||||
|
val getterDescriptor = descriptor.getter ?: throw IllegalStateException("Getter descriptor should not be null")
|
||||||
|
val defaultFunction = createFunction(getterDescriptor).apply {
|
||||||
|
val delegateRef = getDelegateNameRef(descriptor.name.asString())
|
||||||
|
DefaultPropertyTranslator(descriptor, context(), delegateRef).generateDefaultGetterFunction(getterDescriptor, this)
|
||||||
|
}
|
||||||
|
return generateDefaultAccessor(getterDescriptor, defaultFunction)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateDefaultSetter(): JsPropertyInitializer {
|
||||||
|
val setterDescriptor = descriptor.setter ?: throw IllegalStateException("Setter descriptor should not be null")
|
||||||
|
val defaultFunction = createFunction(setterDescriptor).apply {
|
||||||
|
val delegateRef = getDelegateNameRef(descriptor.name.asString())
|
||||||
|
DefaultPropertyTranslator(descriptor, context(), delegateRef).generateDefaultSetterFunction(setterDescriptor, this)
|
||||||
|
}
|
||||||
|
return generateDefaultAccessor(setterDescriptor, defaultFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateDefaultAccessor(accessorDescriptor: VariableAccessorDescriptor, function: JsFunction): JsPropertyInitializer =
|
private fun generateDefaultAccessor(accessorDescriptor: VariableAccessorDescriptor, function: JsFunction): JsPropertyInitializer =
|
||||||
translateFunctionAsEcma5PropertyDescriptor(function, accessorDescriptor, context())
|
translateFunctionAsEcma5PropertyDescriptor(function, accessorDescriptor, context())
|
||||||
|
|
||||||
private fun translateCustomAccessor(expression: KtPropertyAccessor): JsPropertyInitializer =
|
private fun translateCustomAccessor(expression: KtPropertyAccessor): JsPropertyInitializer {
|
||||||
Translation.functionTranslator(expression, context()).translateAsEcma5PropertyDescriptor()
|
val descriptor = BindingUtils.getFunctionDescriptor(bindingContext(), expression)
|
||||||
|
val function = JsFunction(context().getScopeForDescriptor(descriptor), JsBlock(), descriptor.toString())
|
||||||
|
return Translation.functionTranslator(expression, context(), function).translateAsEcma5PropertyDescriptor()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createFunction(descriptor: VariableAccessorDescriptor) =
|
||||||
|
JsFunction(context().getScopeForDescriptor(descriptor), JsBlock(), accessorDescription(descriptor))
|
||||||
|
|
||||||
private fun accessorDescription(accessorDescriptor: VariableAccessorDescriptor): String {
|
private fun accessorDescription(accessorDescriptor: VariableAccessorDescriptor): String {
|
||||||
val accessorType =
|
val accessorType =
|
||||||
|
|||||||
+8
-11
@@ -201,13 +201,12 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
|||||||
if (delegateExpression != null) {
|
if (delegateExpression != null) {
|
||||||
SmartList<JsPropertyInitializer> propertyInitializers = new SmartList<JsPropertyInitializer>();
|
SmartList<JsPropertyInitializer> propertyInitializers = new SmartList<JsPropertyInitializer>();
|
||||||
PropertyTranslatorKt.translateAccessors((VariableDescriptorWithAccessors) descriptor, propertyInitializers, context);
|
PropertyTranslatorKt.translateAccessors((VariableDescriptorWithAccessors) descriptor, propertyInitializers, context);
|
||||||
assert propertyInitializers.size() == 1 : descriptor;
|
|
||||||
initializer = propertyInitializers.get(0).getValueExpr();
|
|
||||||
JsPropertyInitializer delegateInitializer = new JsPropertyInitializer(
|
JsPropertyInitializer delegateInitializer = new JsPropertyInitializer(
|
||||||
context.program().getStringLiteral(Namer.getDelegateName(descriptor.getName().asString())),
|
context.program().getStringLiteral(Namer.getDelegateName(descriptor.getName().asString())),
|
||||||
Translation.translateAsExpression(delegateExpression, context)
|
Translation.translateAsExpression(delegateExpression, context)
|
||||||
);
|
);
|
||||||
((JsObjectLiteral) initializer).getPropertyInitializers().add(delegateInitializer);
|
propertyInitializers.add(delegateInitializer);
|
||||||
|
initializer = new JsObjectLiteral(propertyInitializers, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsName name = context.getNameForDescriptor(descriptor);
|
JsName name = context.getNameForDescriptor(descriptor);
|
||||||
@@ -519,11 +518,9 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public JsNode visitObjectLiteralExpression(@NotNull KtObjectLiteralExpression expression, @NotNull TranslationContext context) {
|
public JsNode visitObjectLiteralExpression(@NotNull KtObjectLiteralExpression expression, @NotNull TranslationContext context) {
|
||||||
ClassDescriptor descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), expression.getObjectDeclaration());
|
ClassDescriptor descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), expression.getObjectDeclaration());
|
||||||
ClassTranslator.TranslationResult result = translateClassOrObject(expression.getObjectDeclaration(), descriptor, context);
|
translateClassOrObject(expression.getObjectDeclaration(), descriptor, context);
|
||||||
List<JsPropertyInitializer> properties = result.getProperties();
|
|
||||||
context.getDefinitionPlace().getProperties().addAll(properties);
|
|
||||||
|
|
||||||
JsExpression constructor = context.getQualifiedReference(descriptor);
|
JsExpression constructor = context.getInnerReference(descriptor);
|
||||||
List<DeclarationDescriptor> closure = context.getClassOrConstructorClosure(descriptor);
|
List<DeclarationDescriptor> closure = context.getClassOrConstructorClosure(descriptor);
|
||||||
List<JsExpression> closureArgs = new ArrayList<JsExpression>();
|
List<JsExpression> closureArgs = new ArrayList<JsExpression>();
|
||||||
if (closure != null) {
|
if (closure != null) {
|
||||||
@@ -551,7 +548,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
|||||||
if (superCall != null) {
|
if (superCall != null) {
|
||||||
assert context.getDeclarationDescriptor() != null : "This expression should be inside declaration: " +
|
assert context.getDeclarationDescriptor() != null : "This expression should be inside declaration: " +
|
||||||
PsiUtilsKt.getTextWithLocation(expression);
|
PsiUtilsKt.getTextWithLocation(expression);
|
||||||
TranslationContext superCallContext = context.newDeclaration(context.getDeclarationDescriptor(), result.getDefinitionPlace());
|
TranslationContext superCallContext = context.newDeclaration(context.getDeclarationDescriptor());
|
||||||
closureArgs.addAll(CallArgumentTranslator.translate(superCall, null, superCallContext).getTranslateArguments());
|
closureArgs.addAll(CallArgumentTranslator.translate(superCall, null, superCallContext).getTranslateArguments());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,7 +580,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
|||||||
@Override
|
@Override
|
||||||
public JsNode visitClass(@NotNull KtClass klass, TranslationContext context) {
|
public JsNode visitClass(@NotNull KtClass klass, TranslationContext context) {
|
||||||
ClassDescriptor descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), klass);
|
ClassDescriptor descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), klass);
|
||||||
context.getDefinitionPlace().getProperties().addAll(translateClassOrObject(klass, descriptor, context).getProperties());
|
translateClassOrObject(klass, descriptor, context);
|
||||||
return JsEmpty.INSTANCE;
|
return JsEmpty.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -593,13 +590,13 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
|||||||
return JsEmpty.INSTANCE;
|
return JsEmpty.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ClassTranslator.TranslationResult translateClassOrObject(
|
private static void translateClassOrObject(
|
||||||
@NotNull KtClassOrObject declaration,
|
@NotNull KtClassOrObject declaration,
|
||||||
@NotNull ClassDescriptor descriptor,
|
@NotNull ClassDescriptor descriptor,
|
||||||
@NotNull TranslationContext context
|
@NotNull TranslationContext context
|
||||||
) {
|
) {
|
||||||
JsScope scope = context.getScopeForDescriptor(descriptor);
|
JsScope scope = context.getScopeForDescriptor(descriptor);
|
||||||
TranslationContext classContext = context.innerWithUsageTracker(scope, descriptor);
|
TranslationContext classContext = context.innerWithUsageTracker(scope, descriptor);
|
||||||
return ClassTranslator.translate(declaration, classContext);
|
ClassTranslator.translate(declaration, classContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-11
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.js.translate.context.AliasingContext;
|
|||||||
import org.jetbrains.kotlin.js.translate.context.Namer;
|
import org.jetbrains.kotlin.js.translate.context.Namer;
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
||||||
import org.jetbrains.kotlin.psi.KtDeclarationWithBody;
|
import org.jetbrains.kotlin.psi.KtDeclarationWithBody;
|
||||||
import org.jetbrains.kotlin.psi.KtLambdaExpression;
|
import org.jetbrains.kotlin.psi.KtLambdaExpression;
|
||||||
@@ -44,9 +45,12 @@ import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.setParameters;
|
|||||||
|
|
||||||
public final class FunctionTranslator extends AbstractTranslator {
|
public final class FunctionTranslator extends AbstractTranslator {
|
||||||
@NotNull
|
@NotNull
|
||||||
public static FunctionTranslator newInstance(@NotNull KtDeclarationWithBody function,
|
public static FunctionTranslator newInstance(
|
||||||
@NotNull TranslationContext context) {
|
@NotNull KtDeclarationWithBody declaration,
|
||||||
return new FunctionTranslator(function, context);
|
@NotNull TranslationContext context,
|
||||||
|
@NotNull JsFunction function
|
||||||
|
) {
|
||||||
|
return new FunctionTranslator(declaration, context, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -60,11 +64,12 @@ public final class FunctionTranslator extends AbstractTranslator {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private final FunctionDescriptor descriptor;
|
private final FunctionDescriptor descriptor;
|
||||||
|
|
||||||
private FunctionTranslator(@NotNull KtDeclarationWithBody functionDeclaration, @NotNull TranslationContext context) {
|
private FunctionTranslator(@NotNull KtDeclarationWithBody functionDeclaration, @NotNull TranslationContext context,
|
||||||
|
@NotNull JsFunction function) {
|
||||||
super(context);
|
super(context);
|
||||||
this.descriptor = getFunctionDescriptor(context.bindingContext(), functionDeclaration);
|
this.descriptor = getFunctionDescriptor(context.bindingContext(), functionDeclaration);
|
||||||
this.functionDeclaration = functionDeclaration;
|
this.functionDeclaration = functionDeclaration;
|
||||||
this.functionObject = context().getFunctionObject(descriptor);
|
this.functionObject = function;
|
||||||
assert this.functionObject.getParameters().isEmpty()
|
assert this.functionObject.getParameters().isEmpty()
|
||||||
: message(descriptor, "Function " + functionDeclaration.getText() + " processed for the second time.");
|
: message(descriptor, "Function " + functionDeclaration.getText() + " processed for the second time.");
|
||||||
//NOTE: it's important we compute the context before we start the computation
|
//NOTE: it's important we compute the context before we start the computation
|
||||||
@@ -94,17 +99,21 @@ public final class FunctionTranslator extends AbstractTranslator {
|
|||||||
return TranslationUtils.translateFunctionAsEcma5PropertyDescriptor(functionObject, descriptor, context());
|
return TranslationUtils.translateFunctionAsEcma5PropertyDescriptor(functionObject, descriptor, context());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
public void translateAsMethodWithoutMetadata() {
|
||||||
public JsPropertyInitializer translateAsMethod() {
|
|
||||||
JsName functionName = context().getNameForDescriptor(descriptor);
|
|
||||||
generateFunctionObject();
|
generateFunctionObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JsExpression translateAsMethod() {
|
||||||
|
translateAsMethodWithoutMetadata();
|
||||||
|
|
||||||
if (shouldBeInlined(descriptor) && DescriptorUtilsKt.isEffectivelyPublicApi(descriptor)) {
|
if (shouldBeInlined(descriptor) && DescriptorUtilsKt.isEffectivelyPublicApi(descriptor)) {
|
||||||
InlineMetadata metadata = InlineMetadata.compose(functionObject, descriptor);
|
InlineMetadata metadata = InlineMetadata.compose(functionObject, descriptor);
|
||||||
return new JsPropertyInitializer(functionName.makeRef(), metadata.getFunctionWithMetadata());
|
return metadata.getFunctionWithMetadata();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return functionObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new JsPropertyInitializer(functionName.makeRef(), functionObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateFunctionObject() {
|
private void generateFunctionObject() {
|
||||||
|
|||||||
+20
-6
@@ -21,6 +21,7 @@ import com.google.dart.compiler.backend.js.ast.metadata.*
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||||
import org.jetbrains.kotlin.js.inline.util.getInnerFunction
|
import org.jetbrains.kotlin.js.inline.util.getInnerFunction
|
||||||
|
import org.jetbrains.kotlin.js.inline.util.refreshLabelNames
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.context.getNameForCapturedDescriptor
|
import org.jetbrains.kotlin.js.translate.context.getNameForCapturedDescriptor
|
||||||
import org.jetbrains.kotlin.js.translate.context.hasCapturedExceptContaining
|
import org.jetbrains.kotlin.js.translate.context.hasCapturedExceptContaining
|
||||||
@@ -58,18 +59,27 @@ class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslato
|
|||||||
|
|
||||||
val isRecursive = tracker.isCaptured(descriptor)
|
val isRecursive = tracker.isCaptured(descriptor)
|
||||||
|
|
||||||
if (isRecursive) {
|
lambda.name = if (isRecursive) {
|
||||||
lambda.name = tracker.getNameForCapturedDescriptor(descriptor)
|
tracker.getNameForCapturedDescriptor(descriptor)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
context().getInnerNameForDescriptor(descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tracker.hasCapturedExceptContaining()) {
|
if (tracker.hasCapturedExceptContaining()) {
|
||||||
val lambdaCreator = simpleReturnFunction(invokingContext.scope(), lambda)
|
val lambdaCreator = simpleReturnFunction(invokingContext.scope(), lambda)
|
||||||
|
lambdaCreator.name = context().getInnerNameForDescriptor(descriptor)
|
||||||
lambdaCreator.isLocal = true
|
lambdaCreator.isLocal = true
|
||||||
return lambdaCreator.withCapturedParameters(functionContext, invokingContext, descriptor)
|
if (!isRecursive) {
|
||||||
|
lambda.name = null
|
||||||
|
}
|
||||||
|
return lambdaCreator.withCapturedParameters(functionContext, invokingContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
lambda.isLocal = true
|
lambda.isLocal = true
|
||||||
return invokingContext.define(descriptor, lambda).apply { sideEffects = SideEffectKind.PURE }
|
|
||||||
|
context().addRootStatement(lambda.makeStmt())
|
||||||
|
return lambda.name.makeRef().apply { sideEffects = SideEffectKind.PURE }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ValueParameterDescriptorImpl.WithDestructuringDeclaration.translate(context: TranslationContext): JsVars {
|
fun ValueParameterDescriptorImpl.WithDestructuringDeclaration.translate(context: TranslationContext): JsVars {
|
||||||
@@ -82,8 +92,12 @@ class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslato
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun JsFunction.withCapturedParameters(context: TranslationContext, invokingContext: TranslationContext, descriptor: MemberDescriptor): JsExpression {
|
fun JsFunction.withCapturedParameters(
|
||||||
val ref = invokingContext.define(descriptor, this).apply { sideEffects = SideEffectKind.PURE }
|
context: TranslationContext,
|
||||||
|
invokingContext: TranslationContext
|
||||||
|
): JsExpression {
|
||||||
|
context.addRootStatement(makeStmt())
|
||||||
|
val ref = name.makeRef().apply { sideEffects = SideEffectKind.PURE }
|
||||||
val invocation = JsInvocation(ref).apply { sideEffects = SideEffectKind.PURE }
|
val invocation = JsInvocation(ref).apply { sideEffects = SideEffectKind.PURE }
|
||||||
|
|
||||||
val invocationArguments = invocation.arguments
|
val invocationArguments = invocation.arguments
|
||||||
|
|||||||
+1
-1
@@ -169,7 +169,7 @@ public final class PatternTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
|
|
||||||
ClassDescriptor referencedClass = DescriptorUtils.getClassDescriptorForType(type);
|
ClassDescriptor referencedClass = DescriptorUtils.getClassDescriptorForType(type);
|
||||||
JsNameRef typeName = context().getQualifiedReference(referencedClass);
|
JsNameRef typeName = context().getInnerReference(referencedClass);
|
||||||
return referencedClass.getKind() != ClassKind.OBJECT ? namer().isInstanceOf(typeName) : namer().isInstanceOfObject(typeName);
|
return referencedClass.getKind() != ClassKind.OBJECT ? namer().isInstanceOf(typeName) : namer().isInstanceOfObject(typeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ import org.jetbrains.kotlin.psi.KtDeclarationWithBody;
|
|||||||
import org.jetbrains.kotlin.psi.KtExpression;
|
import org.jetbrains.kotlin.psi.KtExpression;
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
import org.jetbrains.kotlin.psi.KtNamedFunction;
|
import org.jetbrains.kotlin.psi.KtNamedFunction;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
|
||||||
@@ -66,7 +65,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import static org.jetbrains.kotlin.js.translate.general.ModuleWrapperTranslation.wrapIfNecessary;
|
import static org.jetbrains.kotlin.js.translate.general.ModuleWrapperTranslation.wrapIfNecessary;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getFunctionDescriptor;
|
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getFunctionDescriptor;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.ErrorReportingUtils.message;
|
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.convertToStatement;
|
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.convertToStatement;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.toStringLiteralList;
|
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.toStringLiteralList;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.mutator.LastExpressionMutator.mutateLastExpression;
|
import static org.jetbrains.kotlin.js.translate.utils.mutator.LastExpressionMutator.mutateLastExpression;
|
||||||
@@ -81,9 +79,12 @@ public final class Translation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static FunctionTranslator functionTranslator(@NotNull KtDeclarationWithBody function,
|
public static FunctionTranslator functionTranslator(
|
||||||
@NotNull TranslationContext context) {
|
@NotNull KtDeclarationWithBody declaration,
|
||||||
return FunctionTranslator.newInstance(function, context);
|
@NotNull TranslationContext context,
|
||||||
|
@NotNull JsFunction function
|
||||||
|
) {
|
||||||
|
return FunctionTranslator.newInstance(declaration, context, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -252,17 +253,16 @@ public final class Translation {
|
|||||||
) {
|
) {
|
||||||
StaticContext staticContext = StaticContext.generateStaticContext(bindingTrace, config, moduleDescriptor);
|
StaticContext staticContext = StaticContext.generateStaticContext(bindingTrace, config, moduleDescriptor);
|
||||||
JsProgram program = staticContext.getProgram();
|
JsProgram program = staticContext.getProgram();
|
||||||
|
|
||||||
// Prohibit using "_" as a variable name
|
|
||||||
program.getRootScope().declareName("_");
|
program.getRootScope().declareName("_");
|
||||||
|
|
||||||
JsFunction rootFunction = JsAstUtils.createFunctionWithEmptyBody(program.getScope());
|
JsFunction rootFunction = staticContext.getRootFunction();
|
||||||
JsBlock rootBlock = rootFunction.getBody();
|
JsBlock rootBlock = rootFunction.getBody();
|
||||||
List<JsStatement> statements = rootBlock.getStatements();
|
List<JsStatement> statements = rootBlock.getStatements();
|
||||||
statements.add(program.getStringLiteral("use strict").makeStmt());
|
|
||||||
|
|
||||||
TranslationContext context = TranslationContext.rootContext(staticContext, rootFunction);
|
TranslationContext context = TranslationContext.rootContext(staticContext, rootFunction);
|
||||||
statements.addAll(PackageDeclarationTranslator.translateFiles(files, context));
|
PackageDeclarationTranslator.translateFiles(files, context);
|
||||||
|
staticContext.postProcess();
|
||||||
|
statements.add(0, program.getStringLiteral("use strict").makeStmt());
|
||||||
defineModule(context, statements, config.getModuleId());
|
defineModule(context, statements, config.getModuleId());
|
||||||
|
|
||||||
mayBeGenerateTests(files, config, rootBlock, context);
|
mayBeGenerateTests(files, config, rootBlock, context);
|
||||||
|
|||||||
+39
-29
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.js.translate.declaration.DelegationTranslator;
|
|||||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
||||||
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator;
|
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils;
|
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils;
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.AstUtilsKt;
|
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.AstUtilsKt;
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||||
@@ -39,9 +40,11 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
|||||||
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument;
|
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -56,16 +59,23 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
private final KtClassOrObject classDeclaration;
|
private final KtClassOrObject classDeclaration;
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JsFunction initFunction;
|
private final JsFunction initFunction;
|
||||||
|
@NotNull
|
||||||
private final TranslationContext context;
|
private final TranslationContext context;
|
||||||
|
@NotNull
|
||||||
|
private final ClassDescriptor classDescriptor;
|
||||||
|
|
||||||
public ClassInitializerTranslator(
|
public ClassInitializerTranslator(
|
||||||
@NotNull KtClassOrObject classDeclaration,
|
@NotNull KtClassOrObject classDeclaration,
|
||||||
@NotNull TranslationContext context
|
@NotNull TranslationContext context,
|
||||||
|
@NotNull JsFunction initFunction
|
||||||
) {
|
) {
|
||||||
super(context);
|
super(context);
|
||||||
this.classDeclaration = classDeclaration;
|
this.classDeclaration = classDeclaration;
|
||||||
this.initFunction = createInitFunction(classDeclaration, context);
|
this.initFunction = initFunction;
|
||||||
this.context = context.contextWithScope(initFunction);
|
this.context = context.contextWithScope(initFunction);
|
||||||
|
classDescriptor = BindingUtils.getClassDescriptor(bindingContext(), classDeclaration);
|
||||||
|
|
||||||
|
fillInitFunction(classDeclaration, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -74,8 +84,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
private static void fillInitFunction(KtClassOrObject declaration, TranslationContext context) {
|
||||||
private static JsFunction createInitFunction(KtClassOrObject declaration, TranslationContext context) {
|
|
||||||
//TODO: it's inconsistent that we have scope for class and function for constructor, currently have problems implementing better way
|
//TODO: it's inconsistent that we have scope for class and function for constructor, currently have problems implementing better way
|
||||||
ClassDescriptor classDescriptor = getClassDescriptor(context.bindingContext(), declaration);
|
ClassDescriptor classDescriptor = getClassDescriptor(context.bindingContext(), declaration);
|
||||||
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||||
@@ -104,20 +113,16 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
}
|
}
|
||||||
ctorFunction.setName(ctorFunction.getScope().declareName(functionName));
|
ctorFunction.setName(ctorFunction.getScope().declareName(functionName));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctorFunction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
public void generateInitializeMethod(DelegationTranslator delegationTranslator) {
|
||||||
public JsFunction generateInitializeMethod(DelegationTranslator delegationTranslator) {
|
|
||||||
ClassDescriptor classDescriptor = getClassDescriptor(bindingContext(), classDeclaration);
|
|
||||||
addOuterClassReference(classDescriptor);
|
addOuterClassReference(classDescriptor);
|
||||||
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||||
|
|
||||||
if (primaryConstructor != null) {
|
if (primaryConstructor != null) {
|
||||||
initFunction.getBody().getStatements().addAll(setDefaultValueForArguments(primaryConstructor, context()));
|
initFunction.getBody().getStatements().addAll(setDefaultValueForArguments(primaryConstructor, context()));
|
||||||
|
|
||||||
mayBeAddCallToSuperMethod(initFunction, classDescriptor);
|
mayBeAddCallToSuperMethod(initFunction);
|
||||||
|
|
||||||
//NOTE: while we translate constructor parameters we also add property initializer statements
|
//NOTE: while we translate constructor parameters we also add property initializer statements
|
||||||
// for properties declared as constructor parameters
|
// for properties declared as constructor parameters
|
||||||
@@ -126,8 +131,6 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
delegationTranslator.addInitCode(initFunction.getBody().getStatements());
|
delegationTranslator.addInitCode(initFunction.getBody().getStatements());
|
||||||
new InitializerVisitor().traverseContainer(classDeclaration, context().innerBlock(initFunction.getBody()));
|
new InitializerVisitor().traverseContainer(classDeclaration, context().innerBlock(initFunction.getBody()));
|
||||||
|
|
||||||
return initFunction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addOuterClassReference(ClassDescriptor classDescriptor) {
|
private void addOuterClassReference(ClassDescriptor classDescriptor) {
|
||||||
@@ -142,26 +145,33 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsExpression generateEnumEntryInstanceCreation(@NotNull KotlinType enumClassType) {
|
public static JsExpression generateEnumEntryInstanceCreation(
|
||||||
ResolvedCall<FunctionDescriptor> superCall = getSuperCall(bindingContext(), classDeclaration);
|
@NotNull TranslationContext context,
|
||||||
|
@NotNull KotlinType enumClassType,
|
||||||
|
@NotNull KtClassOrObject classDeclaration,
|
||||||
|
int ordinal
|
||||||
|
) {
|
||||||
|
ResolvedCall<FunctionDescriptor> superCall = getSuperCall(context.bindingContext(), classDeclaration);
|
||||||
|
|
||||||
if (superCall == null) {
|
if (superCall == null) {
|
||||||
ClassDescriptor classDescriptor = getClassDescriptorForType(enumClassType);
|
ClassDescriptor classDescriptor = getClassDescriptorForType(enumClassType);
|
||||||
JsNameRef reference = context().getQualifiedReference(classDescriptor);
|
JsNameRef reference = context.getInnerReference(classDescriptor);
|
||||||
return new JsNew(reference);
|
JsExpression nameArg = context.program().getStringLiteral(classDeclaration.getName());
|
||||||
|
JsExpression ordinalArg = context.program().getNumberLiteral(ordinal);
|
||||||
|
return new JsNew(reference, Arrays.asList(nameArg, ordinalArg));
|
||||||
}
|
}
|
||||||
|
|
||||||
return CallTranslator.translate(context(), superCall);
|
return CallTranslator.translate(context, superCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mayBeAddCallToSuperMethod(JsFunction initializer, @NotNull ClassDescriptor descriptor) {
|
private void mayBeAddCallToSuperMethod(JsFunction initializer) {
|
||||||
if (classDeclaration.hasModifier(KtTokens.ENUM_KEYWORD)) {
|
if (classDeclaration.hasModifier(KtTokens.ENUM_KEYWORD)) {
|
||||||
addCallToSuperMethod(Collections.<JsExpression>emptyList(), initializer);
|
addCallToSuperMethod(Collections.<JsExpression>emptyList(), initializer);
|
||||||
}
|
}
|
||||||
else if (hasAncestorClass(bindingContext(), classDeclaration)) {
|
else if (hasAncestorClass(bindingContext(), classDeclaration)) {
|
||||||
ResolvedCall<FunctionDescriptor> superCall = getSuperCall(bindingContext(), classDeclaration);
|
ResolvedCall<FunctionDescriptor> superCall = getSuperCall(bindingContext(), classDeclaration);
|
||||||
if (superCall == null) {
|
if (superCall == null) {
|
||||||
if (DescriptorUtils.isEnumEntry(descriptor)) {
|
if (DescriptorUtils.isEnumEntry(classDescriptor)) {
|
||||||
addCallToSuperMethod(Collections.<JsExpression>emptyList(), initializer);
|
addCallToSuperMethod(Collections.<JsExpression>emptyList(), initializer);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -182,18 +192,18 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
if (superclassClosure != null) {
|
if (superclassClosure != null) {
|
||||||
UsageTracker tracker = context.usageTracker();
|
UsageTracker tracker = context.usageTracker();
|
||||||
assert tracker != null : "Closure exists, therefore UsageTracker must exist too. Translating constructor of " +
|
assert tracker != null : "Closure exists, therefore UsageTracker must exist too. Translating constructor of " +
|
||||||
descriptor;
|
classDescriptor;
|
||||||
for (DeclarationDescriptor capturedValue : superclassClosure) {
|
for (DeclarationDescriptor capturedValue : superclassClosure) {
|
||||||
tracker.used(capturedValue);
|
tracker.used(capturedValue);
|
||||||
arguments.add(tracker.getCapturedDescriptorToJsName().get(capturedValue).makeRef());
|
arguments.add(tracker.getCapturedDescriptorToJsName().get(capturedValue).makeRef());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (superDescriptor.getContainingDeclaration().isInner() && descriptor.isInner()) {
|
if (superDescriptor.getContainingDeclaration().isInner() && classDescriptor.isInner()) {
|
||||||
arguments.add(pureFqn(Namer.OUTER_FIELD_NAME, JsLiteral.THIS));
|
arguments.add(pureFqn(Namer.OUTER_FIELD_NAME, JsLiteral.THIS));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DescriptorUtils.isAnonymousObject(descriptor)) {
|
if (!DescriptorUtils.isAnonymousObject(classDescriptor)) {
|
||||||
arguments.addAll(CallArgumentTranslator.translate(superCall, null, context()).getTranslateArguments());
|
arguments.addAll(CallArgumentTranslator.translate(superCall, null, context()).getTranslateArguments());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -225,20 +235,22 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCallToSuperMethod(@NotNull List<JsExpression> arguments, JsFunction initializer) {
|
private void addCallToSuperMethod(@NotNull List<JsExpression> arguments, @NotNull JsFunction initializer) {
|
||||||
if (initializer.getName() == null) {
|
if (initializer.getName() == null) {
|
||||||
JsName ref = context().scope().declareName(Namer.CALLEE_NAME);
|
JsName ref = context().scope().declareName(Namer.CALLEE_NAME);
|
||||||
initializer.setName(ref);
|
initializer.setName(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsInvocation call = new JsInvocation(Namer.getFunctionCallRef(Namer.superMethodNameRef(initializer.getName())));
|
ClassDescriptor superclassDescriptor = DescriptorUtilsKt.getSuperClassOrAny(classDescriptor);
|
||||||
|
JsExpression superConstructorRef = context().getInnerReference(superclassDescriptor);
|
||||||
|
JsInvocation call = new JsInvocation(Namer.getFunctionCallRef(superConstructorRef));
|
||||||
call.getArguments().add(JsLiteral.THIS);
|
call.getArguments().add(JsLiteral.THIS);
|
||||||
call.getArguments().addAll(arguments);
|
call.getArguments().addAll(arguments);
|
||||||
initFunction.getBody().getStatements().add(call.makeStmt());
|
initFunction.getBody().getStatements().add(call.makeStmt());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCallToSuperSecondaryConstructor(@NotNull List<JsExpression> arguments, @NotNull ConstructorDescriptor descriptor) {
|
private void addCallToSuperSecondaryConstructor(@NotNull List<JsExpression> arguments, @NotNull ConstructorDescriptor descriptor) {
|
||||||
JsExpression reference = context.getQualifiedReference(descriptor);
|
JsExpression reference = context.getInnerReference(descriptor);
|
||||||
JsInvocation call = new JsInvocation(reference);
|
JsInvocation call = new JsInvocation(reference);
|
||||||
call.getArguments().addAll(arguments);
|
call.getArguments().addAll(arguments);
|
||||||
call.getArguments().add(JsLiteral.THIS);
|
call.getArguments().add(JsLiteral.THIS);
|
||||||
@@ -257,8 +269,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsParameter translateParameter(@NotNull KtParameter jetParameter) {
|
private JsParameter translateParameter(@NotNull KtParameter jetParameter) {
|
||||||
DeclarationDescriptor parameterDescriptor =
|
DeclarationDescriptor parameterDescriptor = getDescriptorForElement(bindingContext(), jetParameter);
|
||||||
getDescriptorForElement(bindingContext(), jetParameter);
|
|
||||||
JsName parameterName = context().getNameForDescriptor(parameterDescriptor);
|
JsName parameterName = context().getNameForDescriptor(parameterDescriptor);
|
||||||
JsParameter jsParameter = new JsParameter(parameterName);
|
JsParameter jsParameter = new JsParameter(parameterName);
|
||||||
mayBeAddInitializerStatementForProperty(jsParameter, jetParameter);
|
mayBeAddInitializerStatementForProperty(jsParameter, jetParameter);
|
||||||
@@ -267,8 +278,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
private void mayBeAddInitializerStatementForProperty(@NotNull JsParameter jsParameter,
|
private void mayBeAddInitializerStatementForProperty(@NotNull JsParameter jsParameter,
|
||||||
@NotNull KtParameter jetParameter) {
|
@NotNull KtParameter jetParameter) {
|
||||||
PropertyDescriptor propertyDescriptor =
|
PropertyDescriptor propertyDescriptor = getPropertyDescriptorForConstructorParameter(bindingContext(), jetParameter);
|
||||||
getPropertyDescriptorForConstructorParameter(bindingContext(), jetParameter);
|
|
||||||
if (propertyDescriptor == null) {
|
if (propertyDescriptor == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-9
@@ -108,20 +108,20 @@ object CallableReferenceTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translateForExtensionProperty(descriptor: PropertyDescriptor, context: TranslationContext): JsExpression {
|
private fun translateForExtensionProperty(descriptor: PropertyDescriptor, context: TranslationContext): JsExpression {
|
||||||
val jsGetterNameRef = context.getQualifiedReference(descriptor.getter!!)
|
val jsGetterNameRef = context.getInnerReference(descriptor.getter!!)
|
||||||
val propertyName = descriptor.name
|
val propertyName = descriptor.name
|
||||||
val jsPropertyNameAsString = context.program().getStringLiteral(propertyName.asString())
|
val jsPropertyNameAsString = context.program().getStringLiteral(propertyName.asString())
|
||||||
val argumentList = ArrayList<JsExpression>(3)
|
val argumentList = ArrayList<JsExpression>(3)
|
||||||
argumentList.add(jsPropertyNameAsString)
|
argumentList.add(jsPropertyNameAsString)
|
||||||
argumentList.add(jsGetterNameRef)
|
argumentList.add(jsGetterNameRef)
|
||||||
if (descriptor.isVar) {
|
if (descriptor.isVar) {
|
||||||
val jsSetterNameRef = context.getQualifiedReference(descriptor.setter!!)
|
val jsSetterNameRef = context.getInnerReference(descriptor.setter!!)
|
||||||
argumentList.add(jsSetterNameRef)
|
argumentList.add(jsSetterNameRef)
|
||||||
}
|
}
|
||||||
if (AnnotationsUtils.isNativeObject(descriptor))
|
return if (AnnotationsUtils.isNativeObject(descriptor))
|
||||||
return translateForMemberProperty(descriptor, context)
|
translateForMemberProperty(descriptor, context)
|
||||||
else
|
else
|
||||||
return JsInvocation(context.namer().callableRefForExtensionPropertyReference(), argumentList)
|
JsInvocation(context.namer().callableRefForExtensionPropertyReference(), argumentList)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translateForConstructor(descriptor: FunctionDescriptor, context: TranslationContext): JsExpression {
|
private fun translateForConstructor(descriptor: FunctionDescriptor, context: TranslationContext): JsExpression {
|
||||||
@@ -130,8 +130,8 @@ object CallableReferenceTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translateForExtensionFunction(descriptor: FunctionDescriptor, context: TranslationContext): JsExpression {
|
private fun translateForExtensionFunction(descriptor: FunctionDescriptor, context: TranslationContext): JsExpression {
|
||||||
val receiverParameterDescriptor = descriptor.extensionReceiverParameter
|
val receiverParameterDescriptor = descriptor.extensionReceiverParameter ?:
|
||||||
assert(receiverParameterDescriptor != null) { "receiverParameter for extension should not be null" }
|
error("receiverParameter for extension should not be null")
|
||||||
|
|
||||||
val jsFunctionRef = ReferenceTranslator.translateAsFQReference(descriptor, context)
|
val jsFunctionRef = ReferenceTranslator.translateAsFQReference(descriptor, context)
|
||||||
if (descriptor.visibility == Visibilities.LOCAL) {
|
if (descriptor.visibility == Visibilities.LOCAL) {
|
||||||
@@ -139,7 +139,7 @@ object CallableReferenceTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (AnnotationsUtils.isNativeObject(descriptor)) {
|
else if (AnnotationsUtils.isNativeObject(descriptor)) {
|
||||||
val jetType = receiverParameterDescriptor!!.type
|
val jetType = receiverParameterDescriptor.type
|
||||||
val receiverClassDescriptor = DescriptorUtils.getClassDescriptorForType(jetType)
|
val receiverClassDescriptor = DescriptorUtils.getClassDescriptorForType(jetType)
|
||||||
return translateAsMemberFunctionReference(descriptor, receiverClassDescriptor, context)
|
return translateAsMemberFunctionReference(descriptor, receiverClassDescriptor, context)
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,12 @@ object CallableReferenceTranslator {
|
|||||||
classDescriptor: ClassDescriptor,
|
classDescriptor: ClassDescriptor,
|
||||||
context: TranslationContext
|
context: TranslationContext
|
||||||
): JsExpression {
|
): JsExpression {
|
||||||
val jsClassNameRef = context.getQualifiedReference(classDescriptor)
|
val jsClassNameRef = if (AnnotationsUtils.isNativeObject(classDescriptor)) {
|
||||||
|
context.getQualifiedReference(classDescriptor)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
context.getInnerReference(classDescriptor)
|
||||||
|
}
|
||||||
val funName = context.getNameForDescriptor(descriptor)
|
val funName = context.getNameForDescriptor(descriptor)
|
||||||
val funNameAsString = context.program().getStringLiteral(funName.toString())
|
val funNameAsString = context.program().getStringLiteral(funName.toString())
|
||||||
return JsInvocation(context.namer().callableRefForMemberFunctionReference(), jsClassNameRef, funNameAsString)
|
return JsInvocation(context.namer().callableRefForMemberFunctionReference(), jsClassNameRef, funNameAsString)
|
||||||
|
|||||||
+35
-6
@@ -17,15 +17,16 @@
|
|||||||
package org.jetbrains.kotlin.js.translate.reference;
|
package org.jetbrains.kotlin.js.translate.reference;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsInvocation;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
|
||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor;
|
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils;
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||||
import org.jetbrains.kotlin.psi.KtExpression;
|
import org.jetbrains.kotlin.psi.KtExpression;
|
||||||
import org.jetbrains.kotlin.psi.KtQualifiedExpression;
|
import org.jetbrains.kotlin.psi.KtQualifiedExpression;
|
||||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression;
|
import org.jetbrains.kotlin.psi.KtSimpleNameExpression;
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getDescriptorForReferenceExpression;
|
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getDescriptorForReferenceExpression;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getSelectorAsSimpleName;
|
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getSelectorAsSimpleName;
|
||||||
@@ -45,7 +46,20 @@ public final class ReferenceTranslator {
|
|||||||
public static JsExpression translateAsFQReference(@NotNull DeclarationDescriptor referencedDescriptor,
|
public static JsExpression translateAsFQReference(@NotNull DeclarationDescriptor referencedDescriptor,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
JsExpression alias = context.getAliasForDescriptor(referencedDescriptor);
|
JsExpression alias = context.getAliasForDescriptor(referencedDescriptor);
|
||||||
return alias != null ? alias : context.getQualifiedReference(referencedDescriptor);
|
if (alias != null) return alias;
|
||||||
|
|
||||||
|
if (isLocalVarOrFunction(referencedDescriptor) ||
|
||||||
|
AnnotationsUtils.isNativeObject(referencedDescriptor) ||
|
||||||
|
AnnotationsUtils.isLibraryObject(referencedDescriptor)
|
||||||
|
) {
|
||||||
|
return context.getQualifiedReference(referencedDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.getInnerReference(referencedDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isLocalVarOrFunction(DeclarationDescriptor descriptor) {
|
||||||
|
return descriptor.getContainingDeclaration() instanceof FunctionDescriptor && !(descriptor instanceof ClassDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -57,7 +71,22 @@ public final class ReferenceTranslator {
|
|||||||
return alias;
|
return alias;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return context.getQualifiedReference(descriptor);
|
if (DescriptorUtils.isObject(descriptor) || DescriptorUtils.isEnumEntry(descriptor)) {
|
||||||
|
if (AnnotationsUtils.isNativeObject(descriptor)) {
|
||||||
|
return context.getQualifiedReference(descriptor);
|
||||||
|
}
|
||||||
|
else if (!context.isFromCurrentModule(descriptor)) {
|
||||||
|
DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||||
|
assert container != null : "Object must have containing declaration: " + descriptor;
|
||||||
|
JsExpression qualifier = context.getInnerReference(container);
|
||||||
|
return JsAstUtils.pureFqn(context.getNameForDescriptor(descriptor), qualifier);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
JsExpression functionRef = JsAstUtils.pureFqn(context.getNameForObjectInstance((ClassDescriptor) descriptor), null);
|
||||||
|
return new JsInvocation(functionRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return context.getInnerReference(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -339,6 +339,11 @@ public final class JsAstUtils {
|
|||||||
return new JsBinaryOperation(JsBinaryOperator.ASG, left, right);
|
return new JsBinaryOperation(JsBinaryOperator.ASG, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static JsStatement assignmentToThisField(@NotNull String fieldName, @NotNull JsExpression right) {
|
||||||
|
return assignment(new JsNameRef(fieldName, JsLiteral.THIS), right).makeStmt();
|
||||||
|
}
|
||||||
|
|
||||||
public static JsStatement asSyntheticStatement(@NotNull JsExpression expression) {
|
public static JsStatement asSyntheticStatement(@NotNull JsExpression expression) {
|
||||||
JsExpressionStatement statement = new JsExpressionStatement(expression);
|
JsExpressionStatement statement = new JsExpressionStatement(expression);
|
||||||
MetadataProperties.setSynthetic(statement, true);
|
MetadataProperties.setSynthetic(statement, true);
|
||||||
@@ -460,11 +465,12 @@ public final class JsAstUtils {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsInvocation defineProperty(
|
public static JsInvocation defineProperty(
|
||||||
|
@NotNull JsExpression receiver,
|
||||||
@NotNull String name,
|
@NotNull String name,
|
||||||
@NotNull JsObjectLiteral value,
|
@NotNull JsExpression value,
|
||||||
@NotNull TranslationContext context
|
@NotNull JsProgram program
|
||||||
) {
|
) {
|
||||||
return new JsInvocation(DEFINE_PROPERTY, JsLiteral.THIS, context.program().getStringLiteral(name), value);
|
return new JsInvocation(DEFINE_PROPERTY.deepCopy(), receiver, program.getStringLiteral(name), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -544,4 +550,21 @@ public final class JsAstUtils {
|
|||||||
JsUnaryOperation unary = (JsUnaryOperation) expression;
|
JsUnaryOperation unary = (JsUnaryOperation) expression;
|
||||||
return unary.getOperator() == JsUnaryOperator.VOID;
|
return unary.getOperator() == JsUnaryOperator.VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static JsStatement defineGetter(
|
||||||
|
@NotNull JsProgram program,
|
||||||
|
@NotNull JsExpression receiver,
|
||||||
|
@NotNull String name,
|
||||||
|
@NotNull JsExpression body
|
||||||
|
) {
|
||||||
|
JsObjectLiteral propertyLiteral = new JsObjectLiteral(true);
|
||||||
|
propertyLiteral.getPropertyInitializers().add(new JsPropertyInitializer(new JsNameRef("get"), body));
|
||||||
|
return defineProperty(receiver, name, propertyLiteral, program).makeStmt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static JsExpression prototypeOf(@NotNull JsExpression expression) {
|
||||||
|
return pureFqn("prototype", expression);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ public final class JsDescriptorUtils {
|
|||||||
return !isExtension(propertyDescriptor) &&
|
return !isExtension(propertyDescriptor) &&
|
||||||
isDefaultAccessor(propertyDescriptor.getGetter()) &&
|
isDefaultAccessor(propertyDescriptor.getGetter()) &&
|
||||||
isDefaultAccessor(propertyDescriptor.getSetter()) &&
|
isDefaultAccessor(propertyDescriptor.getSetter()) &&
|
||||||
!TranslationUtils.shouldGenerateAccessors(propertyDescriptor) &&
|
!TranslationUtils.shouldAccessViaFunctions(propertyDescriptor) &&
|
||||||
!ModalityKt.isOverridableOrOverrides(propertyDescriptor);
|
!ModalityKt.isOverridableOrOverrides(propertyDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-13
@@ -54,7 +54,7 @@ public final class TranslationUtils {
|
|||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
if (DescriptorUtils.isExtension(descriptor) ||
|
if (DescriptorUtils.isExtension(descriptor) ||
|
||||||
descriptor instanceof PropertyAccessorDescriptor &&
|
descriptor instanceof PropertyAccessorDescriptor &&
|
||||||
shouldGenerateAccessors(((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty())
|
shouldAccessViaFunctions(((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty())
|
||||||
) {
|
) {
|
||||||
return translateExtensionFunctionAsEcma5DataDescriptor(function, descriptor, context);
|
return translateExtensionFunctionAsEcma5DataDescriptor(function, descriptor, context);
|
||||||
}
|
}
|
||||||
@@ -146,19 +146,20 @@ public final class TranslationUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsNameRef backingFieldReference(@NotNull TranslationContext context,
|
public static JsNameRef backingFieldReference(@NotNull TranslationContext context, @NotNull PropertyDescriptor descriptor) {
|
||||||
@NotNull PropertyDescriptor descriptor) {
|
DeclarationDescriptor containingDescriptor = descriptor.getContainingDeclaration();
|
||||||
JsName backingFieldName = context.getNameForDescriptor(descriptor);
|
JsName backingFieldName = containingDescriptor instanceof PackageFragmentDescriptor ?
|
||||||
if(!JsDescriptorUtils.isSimpleFinalProperty(descriptor)) {
|
context.getInnerNameForDescriptor(descriptor) :
|
||||||
|
context.getNameForDescriptor(descriptor);
|
||||||
|
|
||||||
|
if (!JsDescriptorUtils.isSimpleFinalProperty(descriptor) && !(containingDescriptor instanceof PackageFragmentDescriptor)) {
|
||||||
JsName backingFieldMangledName = context.getNameForBackingField(descriptor);
|
JsName backingFieldMangledName = context.getNameForBackingField(descriptor);
|
||||||
backingFieldName = context.declarePropertyOrPropertyAccessorName(descriptor, backingFieldMangledName.getIdent(), false);
|
backingFieldName = context.declarePropertyOrPropertyAccessorName(descriptor, backingFieldMangledName.getIdent(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclarationDescriptor containingDescriptor = descriptor.getContainingDeclaration();
|
|
||||||
JsExpression receiver;
|
JsExpression receiver;
|
||||||
if (containingDescriptor instanceof PackageFragmentDescriptor) {
|
if (containingDescriptor instanceof PackageFragmentDescriptor) {
|
||||||
// used inside package initializer
|
receiver = null;
|
||||||
receiver = JsLiteral.THIS;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
receiver = context.getDispatchReceiver(JsDescriptorUtils.getReceiverParameterForDeclaration(containingDescriptor));
|
receiver = context.getDispatchReceiver(JsDescriptorUtils.getReceiverParameterForDeclaration(containingDescriptor));
|
||||||
@@ -296,22 +297,22 @@ public final class TranslationUtils {
|
|||||||
return !(descriptor instanceof LocalVariableDescriptor) || !((LocalVariableDescriptor) descriptor).isDelegated();
|
return !(descriptor instanceof LocalVariableDescriptor) || !((LocalVariableDescriptor) descriptor).isDelegated();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean shouldGenerateAccessors(@NotNull CallableDescriptor descriptor) {
|
public static boolean shouldAccessViaFunctions(@NotNull CallableDescriptor descriptor) {
|
||||||
if (descriptor instanceof PropertyDescriptor) {
|
if (descriptor instanceof PropertyDescriptor) {
|
||||||
return shouldGenerateAccessors((PropertyDescriptor) descriptor);
|
return shouldAccessViaFunctions((PropertyDescriptor) descriptor);
|
||||||
}
|
}
|
||||||
else if (descriptor instanceof PropertyAccessorDescriptor) {
|
else if (descriptor instanceof PropertyAccessorDescriptor) {
|
||||||
return shouldGenerateAccessors(((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty());
|
return shouldAccessViaFunctions(((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean shouldGenerateAccessors(@NotNull PropertyDescriptor property) {
|
private static boolean shouldAccessViaFunctions(@NotNull PropertyDescriptor property) {
|
||||||
if (AnnotationsUtils.hasJsNameInAccessors(property)) return true;
|
if (AnnotationsUtils.hasJsNameInAccessors(property)) return true;
|
||||||
for (PropertyDescriptor overriddenProperty : property.getOverriddenDescriptors()) {
|
for (PropertyDescriptor overriddenProperty : property.getOverriddenDescriptors()) {
|
||||||
if (shouldGenerateAccessors(overriddenProperty)) return true;
|
if (shouldAccessViaFunctions(overriddenProperty)) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,7 @@ package org.jetbrains.kotlin.js.translate.utils
|
|||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
import com.intellij.util.SmartList
|
import com.intellij.util.SmartList
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.simpleReturnFunction
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.simpleReturnFunction
|
||||||
@@ -29,12 +26,12 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
fun generateDelegateCall(
|
fun generateDelegateCall(
|
||||||
|
classDescriptor: ClassDescriptor,
|
||||||
fromDescriptor: FunctionDescriptor,
|
fromDescriptor: FunctionDescriptor,
|
||||||
toDescriptor: FunctionDescriptor,
|
toDescriptor: FunctionDescriptor,
|
||||||
thisObject: JsExpression,
|
thisObject: JsExpression,
|
||||||
context: TranslationContext
|
context: TranslationContext
|
||||||
): JsPropertyInitializer {
|
) {
|
||||||
val delegateMemberFunctionName = context.getNameForDescriptor(fromDescriptor)
|
|
||||||
val overriddenMemberFunctionName = context.getNameForDescriptor(toDescriptor)
|
val overriddenMemberFunctionName = context.getNameForDescriptor(toDescriptor)
|
||||||
val overriddenMemberFunctionRef = JsNameRef(overriddenMemberFunctionName, thisObject)
|
val overriddenMemberFunctionRef = JsNameRef(overriddenMemberFunctionName, thisObject)
|
||||||
|
|
||||||
@@ -57,7 +54,8 @@ fun generateDelegateCall(
|
|||||||
|
|
||||||
val functionObject = simpleReturnFunction(context.getScopeForDescriptor(fromDescriptor), JsInvocation(overriddenMemberFunctionRef, args))
|
val functionObject = simpleReturnFunction(context.getScopeForDescriptor(fromDescriptor), JsInvocation(overriddenMemberFunctionRef, args))
|
||||||
functionObject.parameters.addAll(parameters)
|
functionObject.parameters.addAll(parameters)
|
||||||
return JsPropertyInitializer(delegateMemberFunctionName.makeRef(), functionObject)
|
|
||||||
|
context.addFunctionToPrototype(classDescriptor, fromDescriptor, functionObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T, S> List<T>.splitToRanges(classifier: (T) -> S): List<Pair<List<T>, S>> {
|
fun <T, S> List<T>.splitToRanges(classifier: (T) -> S): List<Pair<List<T>, S>> {
|
||||||
@@ -86,7 +84,7 @@ fun getReferenceToJsClass(type: KotlinType, context: TranslationContext): JsName
|
|||||||
val classifierDescriptor = type.constructor.declarationDescriptor
|
val classifierDescriptor = type.constructor.declarationDescriptor
|
||||||
|
|
||||||
if (classifierDescriptor is ClassDescriptor) {
|
if (classifierDescriptor is ClassDescriptor) {
|
||||||
val reference = context.getQualifiedReference(classifierDescriptor)
|
val reference = context.getInnerReference(classifierDescriptor)
|
||||||
if (classifierDescriptor.kind == ClassKind.OBJECT) {
|
if (classifierDescriptor.kind == ClassKind.OBJECT) {
|
||||||
referenceToJsClass = JsAstUtils.pureFqn("constructor", JsInvocation(JsNameRef("getPrototypeOf", JsNameRef("Object")), reference))
|
referenceToJsClass = JsAstUtils.pureFqn("constructor", JsInvocation(JsNameRef("getPrototypeOf", JsNameRef("Object")), reference))
|
||||||
}
|
}
|
||||||
@@ -105,3 +103,20 @@ fun getReferenceToJsClass(type: KotlinType, context: TranslationContext): JsName
|
|||||||
|
|
||||||
return referenceToJsClass
|
return referenceToJsClass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun TranslationContext.addFunctionToPrototype(classDescriptor: ClassDescriptor, descriptor: FunctionDescriptor, function: JsExpression) {
|
||||||
|
val prototypeRef = JsAstUtils.prototypeOf(getInnerReference(classDescriptor))
|
||||||
|
val functionRef = JsNameRef(getNameForDescriptor(descriptor), prototypeRef)
|
||||||
|
addRootStatement(JsAstUtils.assignment(functionRef, function).makeStmt())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun TranslationContext.addAccessorsToPrototype(
|
||||||
|
containingClass: ClassDescriptor,
|
||||||
|
propertyDescriptor: PropertyDescriptor,
|
||||||
|
literal: JsObjectLiteral
|
||||||
|
) {
|
||||||
|
val prototypeRef = JsAstUtils.prototypeOf(getInnerReference(containingClass))
|
||||||
|
val propertyName = getNameForDescriptor(propertyDescriptor)
|
||||||
|
val defineProperty = JsAstUtils.defineProperty(prototypeRef, propertyName.ident, literal, program())
|
||||||
|
addRootStatement(defineProperty.makeStmt())
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
class A
|
||||||
|
|
||||||
|
class B {
|
||||||
|
val A.x: String
|
||||||
|
get() = "OK"
|
||||||
|
|
||||||
|
fun result(a: A) = a.x
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() = B().result(A())
|
||||||
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
interface I {
|
||||||
|
fun foo() = "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class A : I
|
||||||
|
|
||||||
|
class B : A()
|
||||||
|
|
||||||
|
fun box() = B().foo()
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
interface I {
|
||||||
|
fun foo() = "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
class A : I
|
||||||
|
|
||||||
|
fun box() = A().foo()
|
||||||
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
interface I {
|
||||||
|
fun foo() = "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
interface J : I
|
||||||
|
|
||||||
|
class A : J
|
||||||
|
|
||||||
|
fun box() = A().foo()
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
interface I {
|
||||||
|
val foo: String
|
||||||
|
get() = "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
class A : I
|
||||||
|
|
||||||
|
fun box() = A().foo
|
||||||
@@ -20,7 +20,7 @@ fun box(): String {
|
|||||||
if (foo + bar != OK) return "$foo + $bar != $OK"
|
if (foo + bar != OK) return "$foo + $bar != $OK"
|
||||||
|
|
||||||
val actualAsString = funToString("actual_0")
|
val actualAsString = funToString("actual_0")
|
||||||
val expectedAsString = funToString("expected_0")
|
val expectedAsString = funToString("expected_0").replace("expected", "actual")
|
||||||
if (actualAsString != expectedAsString) return "$actualAsString != $expectedAsString"
|
if (actualAsString != expectedAsString) return "$actualAsString != $expectedAsString"
|
||||||
if (actual("asd", "12345") != "asd12345") return "${actual("asd", "12345")} != \"asd12345\""
|
if (actual("asd", "12345") != "asd12345") return "${actual("asd", "12345")} != \"asd12345\""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user