Extension points for serialization plugin in JS translator:

* Plugins for JS CLI compiler now can be loaded via -XPlugin option
* New extension point in project
* JS translator modified to accept synthetic declarations and call
 extension.
* Some functions made public to create a small API
This commit is contained in:
Leonid Startsev
2017-08-24 16:42:36 +03:00
committed by Zalim Bashorov
parent 0246b82833
commit a0ddef22ef
15 changed files with 150 additions and 47 deletions
@@ -43,6 +43,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageUtil;
import org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsKt; import org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsKt;
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles; import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser;
import org.jetbrains.kotlin.config.*; import org.jetbrains.kotlin.config.*;
import org.jetbrains.kotlin.incremental.components.LookupTracker; import org.jetbrains.kotlin.incremental.components.LookupTracker;
import org.jetbrains.kotlin.incremental.js.TranslationResultValue; import org.jetbrains.kotlin.incremental.js.TranslationResultValue;
@@ -167,6 +168,9 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
return COMPILATION_ERROR; return COMPILATION_ERROR;
} }
ExitCode plugLoadResult = PluginCliParser.loadPluginsSafe(arguments, configuration);
if (plugLoadResult != ExitCode.OK) return plugLoadResult;
configuration.put(JSConfigurationKeys.LIBRARIES, configureLibraries(arguments, paths, messageCollector)); configuration.put(JSConfigurationKeys.LIBRARIES, configureLibraries(arguments, paths, messageCollector));
ContentRootsKt.addKotlinSourceRoots(configuration, arguments.getFreeArgs()); ContentRootsKt.addKotlinSourceRoots(configuration, arguments.getFreeArgs());
@@ -69,22 +69,8 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
if (it != OK) return it if (it != OK) return it
} }
try { val plugLoadResult = PluginCliParser.loadPluginsSafe(arguments, configuration)
PluginCliParser.loadPlugins(arguments, configuration) if (plugLoadResult != ExitCode.OK) return plugLoadResult
}
catch (e: PluginCliOptionProcessingException) {
val message = e.message + "\n\n" + cliPluginUsageString(e.pluginId, e.options)
messageCollector.report(ERROR, message)
return INTERNAL_ERROR
}
catch (e: CliOptionProcessingException) {
messageCollector.report(ERROR, e.message!!)
return INTERNAL_ERROR
}
catch (t: Throwable) {
MessageCollectorUtil.reportException(messageCollector, t)
return INTERNAL_ERROR
}
if (!arguments.script && arguments.buildFile == null) { if (!arguments.script && arguments.buildFile == null) {
for (arg in arguments.freeArgs) { for (arg in arguments.freeArgs) {
@@ -89,6 +89,7 @@ import org.jetbrains.kotlin.extensions.DeclarationAttributeAltererExtension
import org.jetbrains.kotlin.extensions.PreprocessedVirtualFileFactoryExtension import org.jetbrains.kotlin.extensions.PreprocessedVirtualFileFactoryExtension
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.js.translate.extensions.JsSyntheticTranslateExtension
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
import org.jetbrains.kotlin.load.kotlin.MetadataFinderFactory import org.jetbrains.kotlin.load.kotlin.MetadataFinderFactory
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager
@@ -165,6 +166,7 @@ class KotlinCoreEnvironment private constructor(
StorageComponentContainerContributor.registerExtensionPoint(project) StorageComponentContainerContributor.registerExtensionPoint(project)
DeclarationAttributeAltererExtension.registerExtensionPoint(project) DeclarationAttributeAltererExtension.registerExtensionPoint(project)
PreprocessedVirtualFileFactoryExtension.registerExtensionPoint(project) PreprocessedVirtualFileFactoryExtension.registerExtensionPoint(project)
JsSyntheticTranslateExtension.registerExtensionPoint(project)
for (registrar in configuration.getList(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS)) { for (registrar in configuration.getList(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS)) {
registrar.registerProjectComponents(project, configuration) registrar.registerProjectComponents(project, configuration)
@@ -17,7 +17,11 @@
package org.jetbrains.kotlin.cli.jvm.plugins package org.jetbrains.kotlin.cli.jvm.plugins
import com.intellij.util.containers.MultiMap import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil
import org.jetbrains.kotlin.cli.jvm.BundledCompilerPlugins import org.jetbrains.kotlin.cli.jvm.BundledCompilerPlugins
import org.jetbrains.kotlin.compiler.plugin.* import org.jetbrains.kotlin.compiler.plugin.*
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
@@ -26,6 +30,30 @@ import java.net.URL
import java.util.* import java.util.*
object PluginCliParser { object PluginCliParser {
@JvmStatic
fun loadPluginsSafe(arguments: CommonCompilerArguments, configuration: CompilerConfiguration): ExitCode {
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
try {
PluginCliParser.loadPlugins(arguments, configuration)
}
catch (e: PluginCliOptionProcessingException) {
val message = e.message + "\n\n" + cliPluginUsageString(e.pluginId, e.options)
messageCollector.report(CompilerMessageSeverity.ERROR, message)
return ExitCode.INTERNAL_ERROR
}
catch (e: CliOptionProcessingException) {
messageCollector.report(CompilerMessageSeverity.ERROR, e.message!!)
return ExitCode.INTERNAL_ERROR
}
catch (t: Throwable) {
MessageCollectorUtil.reportException(messageCollector, t)
return ExitCode.INTERNAL_ERROR
}
return ExitCode.OK
}
@JvmStatic @JvmStatic
fun loadPlugins(arguments: CommonCompilerArguments, configuration: CompilerConfiguration) { fun loadPlugins(arguments: CommonCompilerArguments, configuration: CompilerConfiguration) {
val classLoader = PluginURLClassLoader( val classLoader = PluginURLClassLoader(
+3
View File
@@ -14,6 +14,9 @@
<extensionPoint name="syntheticResolveExtension" <extensionPoint name="syntheticResolveExtension"
interface="org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension" interface="org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension"
area="IDEA_PROJECT"/> area="IDEA_PROJECT"/>
<extensionPoint name="jsSyntheticTranslateExtension"
interface="org.jetbrains.kotlin.js.translate.extensions.JsSyntheticTranslateExtension"
area="IDEA_PROJECT"/>
<extensionPoint name="findUsagesHandlerDecorator" <extensionPoint name="findUsagesHandlerDecorator"
interface="org.jetbrains.kotlin.plugin.findUsages.handlers.KotlinFindUsagesHandlerDecorator" interface="org.jetbrains.kotlin.plugin.findUsages.handlers.KotlinFindUsagesHandlerDecorator"
area="IDEA_PROJECT"/> area="IDEA_PROJECT"/>
@@ -116,17 +116,20 @@ abstract class AbstractDeclarationVisitor : TranslatorVisitor<Unit>() {
return innerContext.wrapWithInlineMetadata(function, descriptor, context.config) return innerContext.wrapWithInlineMetadata(function, descriptor, context.config)
} }
protected abstract fun addFunction( // used from kotlinx.serialization
abstract fun addFunction(
descriptor: FunctionDescriptor, descriptor: FunctionDescriptor,
expression: JsExpression?, expression: JsExpression?,
psi: KtElement psi: KtElement?
) )
protected abstract fun addProperty( // used from kotlinx.serialization
abstract fun addProperty(
descriptor: PropertyDescriptor, descriptor: PropertyDescriptor,
getter: JsExpression, getter: JsExpression,
setter: JsExpression? setter: JsExpression?
) )
protected abstract fun getBackingFieldReference(descriptor: PropertyDescriptor): JsExpression // used from kotlinx.serialization
abstract fun getBackingFieldReference(descriptor: PropertyDescriptor): JsExpression
} }
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.js.translate.declaration package org.jetbrains.kotlin.js.translate.declaration
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
@@ -25,6 +26,7 @@ import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator
import org.jetbrains.kotlin.js.translate.context.* import org.jetbrains.kotlin.js.translate.context.*
import org.jetbrains.kotlin.js.translate.expression.translateAndAliasParameters import org.jetbrains.kotlin.js.translate.expression.translateAndAliasParameters
import org.jetbrains.kotlin.js.translate.expression.translateFunction import org.jetbrains.kotlin.js.translate.expression.translateFunction
import org.jetbrains.kotlin.js.translate.extensions.JsSyntheticTranslateExtension
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.reference.ReferenceTranslator import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
@@ -38,12 +40,16 @@ import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.toInvocationWith
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtEnumEntry import org.jetbrains.kotlin.psi.KtEnumEntry
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.psi.KtSecondaryConstructor import org.jetbrains.kotlin.psi.KtSecondaryConstructor
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptor
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.getClassDescriptorForType import org.jetbrains.kotlin.resolve.DescriptorUtils.getClassDescriptorForType
import org.jetbrains.kotlin.resolve.DescriptorUtils.getClassDescriptorForTypeConstructor import org.jetbrains.kotlin.resolve.DescriptorUtils.getClassDescriptorForTypeConstructor
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.resolve.source.getPsi
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
@@ -54,7 +60,7 @@ import org.jetbrains.kotlin.utils.DFS
* Generates a definition of a single class. * Generates a definition of a single class.
*/ */
class ClassTranslator private constructor( class ClassTranslator private constructor(
private val classDeclaration: KtClassOrObject, private val classDeclaration: KtPureClassOrObject,
context: TranslationContext, context: TranslationContext,
private val enumInitializerName: JsName?, private val enumInitializerName: JsName?,
private val ordinal: Int? private val ordinal: Int?
@@ -83,11 +89,30 @@ class ClassTranslator private constructor(
translatePropertiesAsConstructorParameters(nonConstructorContext) translatePropertiesAsConstructorParameters(nonConstructorContext)
val bodyVisitor = DeclarationBodyVisitor(descriptor, nonConstructorContext, enumInitFunction) val bodyVisitor = DeclarationBodyVisitor(descriptor, nonConstructorContext, enumInitFunction)
bodyVisitor.traverseContainer(classDeclaration, nonConstructorContext) bodyVisitor.traverseContainer(classDeclaration, nonConstructorContext)
val companionDescriptor = descriptor.companionObjectDescriptor
// add non-declared (therefore, not traversed) synthetic companion object
if (companionDescriptor is SyntheticClassOrObjectDescriptor) {
bodyVisitor.generateClassOrObject(companionDescriptor.syntheticDeclaration, nonConstructorContext, true)
}
// synthetic nested classes
descriptor
.unsubstitutedMemberScope
.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS, MemberScope.ALL_NAME_FILTER)
.asSequence()
.filterIsInstance<SyntheticClassOrObjectDescriptor>()
.filter { it != companionDescriptor }
.forEach { bodyVisitor.generateClassOrObject(it.syntheticDeclaration, nonConstructorContext, false) }
// other synthetic initializers, properties and functions
generateClassSyntheticParts(nonConstructorContext, bodyVisitor)
mayBeAddThrowableProperties(context) mayBeAddThrowableProperties(context)
constructorFunction.body.statements += bodyVisitor.initializerStatements constructorFunction.body.statements += bodyVisitor.initializerStatements
delegationTranslator.generateDelegated() delegationTranslator.generateDelegated()
val companionDescriptor = descriptor.companionObjectDescriptor
if (enumInitFunction != null && companionDescriptor != null) { if (enumInitFunction != null && companionDescriptor != null) {
val initInvocation = JsInvocation(JsAstUtils.pureFqn(context().getNameForObjectInstance(companionDescriptor), null)) val initInvocation = JsInvocation(JsAstUtils.pureFqn(context().getNameForObjectInstance(companionDescriptor), null))
enumInitFunction.body.statements += JsAstUtils.asSyntheticStatement(initInvocation.source(companionDescriptor.source.getPsi())) enumInitFunction.body.statements += JsAstUtils.asSyntheticStatement(initInvocation.source(companionDescriptor.source.getPsi()))
@@ -100,7 +125,7 @@ class ClassTranslator private constructor(
addSuperclassReferences() addSuperclassReferences()
classDeclaration.secondaryConstructors.forEach { generateSecondaryConstructor(context, it) } classDeclaration.secondaryConstructors.forEach { generateSecondaryConstructor(context, it) }
if (descriptor.isData) { if (descriptor.isData && classDeclaration is KtClassOrObject) {
JsDataClassGenerator(classDeclaration, context).generate() JsDataClassGenerator(classDeclaration, context).generate()
} }
@@ -122,6 +147,11 @@ class ClassTranslator private constructor(
descriptor.getSuperClassNotAny()?.let { ReferenceTranslator.translateAsTypeReference(it, context) } descriptor.getSuperClassNotAny()?.let { ReferenceTranslator.translateAsTypeReference(it, context) }
} }
private fun generateClassSyntheticParts(context: TranslationContext, declarationVisitor: DeclarationBodyVisitor) {
val ext = JsSyntheticTranslateExtension.getInstances(context.config.project)
ext.forEach { it.generateClassSyntheticParts(classDeclaration, descriptor, declarationVisitor, context) }
}
private fun TranslationContext.withUsageTrackerIfNecessary(innerDescriptor: MemberDescriptor): TranslationContext { private fun TranslationContext.withUsageTrackerIfNecessary(innerDescriptor: MemberDescriptor): TranslationContext {
return if (isLocalClass) { return if (isLocalClass) {
innerWithUsageTracker(innerDescriptor) innerWithUsageTracker(innerDescriptor)
@@ -475,7 +505,10 @@ class ClassTranslator private constructor(
} }
private fun generateEnumStandardMethods(entries: List<ClassDescriptor>) { private fun generateEnumStandardMethods(entries: List<ClassDescriptor>) {
EnumTranslator(context(), descriptor, entries, classDeclaration).generateStandardMethods() // synthetic enums aren't supported yet
if (classDeclaration is PsiElement) {
EnumTranslator(context(), descriptor, entries, classDeclaration).generateStandardMethods()
}
} }
private fun mayBeAddThrowableProperties(context: TranslationContext) { private fun mayBeAddThrowableProperties(context: TranslationContext) {
@@ -498,6 +531,10 @@ class ClassTranslator private constructor(
private fun <T : JsNode> T.withDefaultLocation(): T = apply { source = classDeclaration } private fun <T : JsNode> T.withDefaultLocation(): T = apply { source = classDeclaration }
companion object { companion object {
@JvmStatic fun translate(classDeclaration: KtPureClassOrObject, context: TranslationContext) {
ClassTranslator(classDeclaration, context, null, null).translate()
}
@JvmStatic fun translate(classDeclaration: KtClassOrObject, context: TranslationContext, enumInitializerName: JsName?) { @JvmStatic fun translate(classDeclaration: KtClassOrObject, context: TranslationContext, enumInitializerName: JsName?) {
return ClassTranslator(classDeclaration, context, enumInitializerName, null).translate() return ClassTranslator(classDeclaration, context, enumInitializerName, null).translate()
} }
@@ -28,8 +28,8 @@ import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getClassDescriptor
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.getSupertypesWithoutFakes import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOwnParametersWithDefaultValue
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOrInheritsParametersWithDefaultValue import org.jetbrains.kotlin.resolve.descriptorUtil.hasOrInheritsParametersWithDefaultValue
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOwnParametersWithDefaultValue
class DeclarationBodyVisitor( class DeclarationBodyVisitor(
private val containingClass: ClassDescriptor, private val containingClass: ClassDescriptor,
@@ -55,6 +55,16 @@ class DeclarationBodyVisitor(
} }
} }
fun generateClassOrObject(classOrObject: KtPureClassOrObject, context: TranslationContext, needCompanionInitializer: Boolean = false) {
ClassTranslator.translate(classOrObject, context)
val descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), classOrObject)
context.export(descriptor)
if (needCompanionInitializer) {
addInitializerStatement(JsInvocation(context.getNameForObjectInstance(descriptor).makeRef())
.source(classOrObject).makeStmt())
}
}
override fun visitEnumEntry(enumEntry: KtEnumEntry, context: TranslationContext) { override fun visitEnumEntry(enumEntry: KtEnumEntry, context: TranslationContext) {
val enumInitializer = this.enumInitializer!! val enumInitializer = this.enumInitializer!!
val descriptor = getClassDescriptor(context.bindingContext(), enumEntry) val descriptor = getClassDescriptor(context.bindingContext(), enumEntry)
@@ -95,11 +105,12 @@ class DeclarationBodyVisitor(
override fun visitSecondaryConstructor(constructor: KtSecondaryConstructor, data: TranslationContext) { } override fun visitSecondaryConstructor(constructor: KtSecondaryConstructor, data: TranslationContext) { }
private fun addInitializerStatement(statement: JsStatement) { // used from kotlinx.serialization
fun addInitializerStatement(statement: JsStatement) {
initializerStatements.add(statement) initializerStatements.add(statement)
} }
override fun addFunction(descriptor: FunctionDescriptor, expression: JsExpression?, psi: KtElement) { override fun addFunction(descriptor: FunctionDescriptor, expression: JsExpression?, psi: KtElement?) {
if (!descriptor.hasOrInheritsParametersWithDefaultValue() || !descriptor.isOverridableOrOverrides) { if (!descriptor.hasOrInheritsParametersWithDefaultValue() || !descriptor.isOverridableOrOverrides) {
if (expression != null) { if (expression != null) {
context.addDeclarationStatement(context.addFunctionToPrototype(containingClass, descriptor, expression)) context.addDeclarationStatement(context.addFunctionToPrototype(containingClass, descriptor, expression))
@@ -116,7 +127,7 @@ class DeclarationBodyVisitor(
if (descriptor.hasOwnParametersWithDefaultValue()) { if (descriptor.hasOwnParametersWithDefaultValue()) {
val caller = JsFunction(context.getScopeForDescriptor(containingClass), JsBlock(), "") val caller = JsFunction(context.getScopeForDescriptor(containingClass), JsBlock(), "")
caller.source = psi.finalElement caller.source = psi?.finalElement
val callerContext = context val callerContext = context
.newDeclaration(descriptor) .newDeclaration(descriptor)
.translateAndAliasParameters(descriptor, caller.parameters) .translateAndAliasParameters(descriptor, caller.parameters)
@@ -27,15 +27,15 @@ import org.jetbrains.kotlin.js.translate.general.Translation
import org.jetbrains.kotlin.js.translate.utils.* import org.jetbrains.kotlin.js.translate.utils.*
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.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.psi.KtSuperTypeListEntry import org.jetbrains.kotlin.psi.KtSuperTypeListEntry
import org.jetbrains.kotlin.resolve.DelegationResolver import org.jetbrains.kotlin.resolve.DelegationResolver
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty
class DelegationTranslator( class DelegationTranslator(
classDeclaration: KtClassOrObject, classDeclaration: KtPureClassOrObject,
context: TranslationContext context: TranslationContext
) : AbstractTranslator(context) { ) : AbstractTranslator(context) {
@@ -45,7 +45,7 @@ class FileDeclarationVisitor(private val context: TranslationContext) : Abstract
super.visitProperty(expression, context) super.visitProperty(expression, context)
} }
override fun addFunction(descriptor: FunctionDescriptor, expression: JsExpression?, psi: KtElement) { override fun addFunction(descriptor: FunctionDescriptor, expression: JsExpression?, psi: KtElement?) {
if (expression == null) return if (expression == null) return
addFunctionButNotExport(descriptor, expression) addFunctionButNotExport(descriptor, expression)
context.export(descriptor) context.export(descriptor)
@@ -610,6 +610,6 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@NotNull TranslationContext context @NotNull TranslationContext context
) { ) {
TranslationContext classContext = context.innerWithUsageTracker(descriptor); TranslationContext classContext = context.innerWithUsageTracker(descriptor);
ClassTranslator.translate(declaration, classContext, null); ClassTranslator.translate(declaration, classContext);
} }
} }
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2017 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.extensions
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.declaration.DeclarationBodyVisitor
import org.jetbrains.kotlin.psi.KtPureClassOrObject
interface JsSyntheticTranslateExtension {
companion object : ProjectExtensionDescriptor<JsSyntheticTranslateExtension>(
"org.jetbrains.kotlin.jsSyntheticTranslateExtension", JsSyntheticTranslateExtension::class.java)
fun generateClassSyntheticParts(declaration: KtPureClassOrObject, descriptor: ClassDescriptor, translator: DeclarationBodyVisitor, context: TranslationContext)
}
@@ -37,10 +37,7 @@ import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils;
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;
import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.KtClassOrObject; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.KtEnumEntry;
import org.jetbrains.kotlin.psi.KtExpression;
import org.jetbrains.kotlin.psi.KtParameter;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt; import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt; import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
@@ -62,7 +59,7 @@ import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getPrimaryConstru
public final class ClassInitializerTranslator extends AbstractTranslator { public final class ClassInitializerTranslator extends AbstractTranslator {
@NotNull @NotNull
private final KtClassOrObject classDeclaration; private final KtPureClassOrObject classDeclaration;
@NotNull @NotNull
private final JsFunction initFunction; private final JsFunction initFunction;
@NotNull @NotNull
@@ -75,7 +72,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
private int ordinal; private int ordinal;
public ClassInitializerTranslator( public ClassInitializerTranslator(
@NotNull KtClassOrObject classDeclaration, @NotNull KtPureClassOrObject classDeclaration,
@NotNull TranslationContext context, @NotNull TranslationContext context,
@NotNull JsFunction initFunction @NotNull JsFunction initFunction
) { ) {
@@ -110,8 +107,8 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
initFunction.getParameters().addAll(translatePrimaryConstructorParameters()); initFunction.getParameters().addAll(translatePrimaryConstructorParameters());
// Initialize enum 'name' and 'ordinal' before translating property initializers. // Initialize enum 'name' and 'ordinal' before translating property initializers.
if (classDescriptor.getKind() == ClassKind.ENUM_CLASS) { if (classDescriptor.getKind() == ClassKind.ENUM_CLASS && classDeclaration instanceof PsiElement) {
addEnumClassParameters(initFunction, classDeclaration); addEnumClassParameters(initFunction, (PsiElement) classDeclaration);
} }
} }
@@ -176,7 +173,8 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
} }
private void mayBeAddCallToSuperMethod(JsFunction initializer) { private void mayBeAddCallToSuperMethod(JsFunction initializer) {
if (classDeclaration.hasModifier(KtTokens.ENUM_KEYWORD)) { if (classDeclaration instanceof KtClassOrObject &&
((KtClassOrObject) classDeclaration).hasModifier(KtTokens.ENUM_KEYWORD)) {
addCallToSuperMethod(Collections.emptyList(), initializer, classDeclaration); addCallToSuperMethod(Collections.emptyList(), initializer, classDeclaration);
} }
else if (hasAncestorClass(bindingContext(), classDeclaration)) { else if (hasAncestorClass(bindingContext(), classDeclaration)) {
@@ -330,7 +328,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
return additionalArguments; return additionalArguments;
} }
private void addCallToSuperMethod(@NotNull List<JsExpression> arguments, @NotNull JsFunction initializer, @NotNull PsiElement psi) { private void addCallToSuperMethod(@NotNull List<JsExpression> arguments, @NotNull JsFunction initializer, @NotNull KtPureElement psi) {
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);
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptorKt;
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 org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
@@ -61,8 +62,8 @@ public final class BindingUtils {
@NotNull @NotNull
public static ClassDescriptor getClassDescriptor(@NotNull BindingContext context, public static ClassDescriptor getClassDescriptor(@NotNull BindingContext context,
@NotNull KtClassOrObject declaration) { @NotNull KtPureClassOrObject declaration) {
return BindingContextUtils.getNotNull(context, BindingContext.CLASS, declaration); return SyntheticClassOrObjectDescriptorKt.findClassDescriptor(declaration, context);
} }
@NotNull @NotNull
@@ -84,7 +85,7 @@ public final class BindingUtils {
return (KtParameter) result; return (KtParameter) result;
} }
public static boolean hasAncestorClass(@NotNull BindingContext context, @NotNull KtClassOrObject classDeclaration) { public static boolean hasAncestorClass(@NotNull BindingContext context, @NotNull KtPureClassOrObject classDeclaration) {
ClassDescriptor classDescriptor = getClassDescriptor(context, classDeclaration); ClassDescriptor classDescriptor = getClassDescriptor(context, classDeclaration);
List<ClassDescriptor> superclassDescriptors = DescriptorUtils.getSuperclassDescriptors(classDescriptor); List<ClassDescriptor> superclassDescriptors = DescriptorUtils.getSuperclassDescriptors(classDescriptor);
return (JsDescriptorUtils.findAncestorClass(superclassDescriptors) != null); return (JsDescriptorUtils.findAncestorClass(superclassDescriptors) != null);
@@ -231,7 +232,7 @@ public final class BindingUtils {
@Nullable @Nullable
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static ResolvedCall<FunctionDescriptor> getSuperCall(@NotNull BindingContext context, KtClassOrObject classDeclaration) { public static ResolvedCall<FunctionDescriptor> getSuperCall(@NotNull BindingContext context, KtPureClassOrObject classDeclaration) {
for (KtSuperTypeListEntry specifier : classDeclaration.getSuperTypeListEntries()) { for (KtSuperTypeListEntry specifier : classDeclaration.getSuperTypeListEntries()) {
if (specifier instanceof KtSuperTypeCallEntry) { if (specifier instanceof KtSuperTypeCallEntry) {
KtSuperTypeCallEntry superCall = (KtSuperTypeCallEntry) specifier; KtSuperTypeCallEntry superCall = (KtSuperTypeCallEntry) specifier;
@@ -98,7 +98,7 @@ public final class PsiUtils {
} }
@NotNull @NotNull
public static List<KtParameter> getPrimaryConstructorParameters(@NotNull KtClassOrObject classDeclaration) { public static List<KtParameter> getPrimaryConstructorParameters(@NotNull KtPureClassOrObject classDeclaration) {
if (classDeclaration instanceof KtClass) { if (classDeclaration instanceof KtClass) {
return classDeclaration.getPrimaryConstructorParameters(); return classDeclaration.getPrimaryConstructorParameters();
} }