From ded46843c226ce2a4d0f88f2bdb110f729db7e11 Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Thu, 29 Jan 2015 12:59:26 +0300 Subject: [PATCH] JS: generate metadata for public inline functions --- .../resolve/calls/checkers/InlineChecker.java | 21 ++-- .../kotlin/resolve/DescriptorUtils.kt | 13 +++ .../analyze/TopDownAnalyzerFacadeForJS.java | 2 +- .../util/collectors/FunctionCollector.kt | 25 ++-- .../kotlin/js/translate/context/Namer.java | 32 ++++++ .../js/translate/context/StaticContext.java | 19 ---- .../expression/FunctionTranslator.java | 18 +-- .../js/translate/expression/InlineMetadata.kt | 107 ++++++++++++++++++ .../reference/CallExpressionTranslator.java | 4 + .../js/translate/utils/JsDescriptorUtils.java | 32 ++++++ js/js.translator/testData/kotlin_lib_ecma5.js | 4 + 11 files changed, 225 insertions(+), 52 deletions(-) create mode 100644 js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/InlineMetadata.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java index 1b39387532b..d6e1e4a2d68 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java @@ -45,6 +45,7 @@ import java.util.Set; import static org.jetbrains.kotlin.resolve.InlineDescriptorUtils.allowsNonLocalReturns; import static org.jetbrains.kotlin.resolve.InlineDescriptorUtils.checkNonLocalReturnUsage; +import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getIsEffectivelyPublicApi; class InlineChecker implements CallChecker { @@ -57,7 +58,7 @@ class InlineChecker implements CallChecker { public InlineChecker(@NotNull SimpleFunctionDescriptor descriptor) { assert descriptor.getInlineStrategy().isInline() : "This extension should be created only for inline functions but not " + descriptor; this.descriptor = descriptor; - this.isEffectivelyPublicApiFunction = isEffectivelyPublicApi(descriptor); + this.isEffectivelyPublicApiFunction = getIsEffectivelyPublicApi(descriptor); for (ValueParameterDescriptor param : descriptor.getValueParameters()) { if (isInlinableParameter(param)) { @@ -242,24 +243,22 @@ class InlineChecker implements CallChecker { } private void checkVisibility(@NotNull CallableDescriptor declarationDescriptor, @NotNull JetElement expression, @NotNull BasicCallResolutionContext context){ - if (isEffectivelyPublicApiFunction && !isEffectivelyPublicApi(declarationDescriptor) && declarationDescriptor.getVisibility() != Visibilities.LOCAL) { + boolean declarationDescriptorIsPublicApi = getIsEffectivelyPublicApi(declarationDescriptor) || isDefinedInInlineFunction(declarationDescriptor); + if (isEffectivelyPublicApiFunction && !declarationDescriptorIsPublicApi && declarationDescriptor.getVisibility() != Visibilities.LOCAL) { context.trace.report(Errors.INVISIBLE_MEMBER_FROM_INLINE.on(expression, declarationDescriptor, descriptor)); } } - private boolean isEffectivelyPublicApi(@NotNull DeclarationDescriptorWithVisibility startDescriptor) { + private boolean isDefinedInInlineFunction(@NotNull DeclarationDescriptorWithVisibility startDescriptor) { DeclarationDescriptorWithVisibility parent = startDescriptor; + while (parent != null) { - if (!parent.getVisibility().isPublicAPI()) { - if (parent.getContainingDeclaration() == descriptor) { - //skip all defined in inline function - return true; - } - return false; - } + if (parent.getContainingDeclaration() == descriptor) return true; + parent = DescriptorUtils.getParentOfType(parent, DeclarationDescriptorWithVisibility.class); } - return true; + + return false; } private void checkNonLocalReturn( diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt index ea3bfc73967..c99a8622ba9 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt @@ -68,4 +68,17 @@ public val ClassDescriptor.classObjectDescriptor: ClassDescriptor? } else -> getDefaultObjectDescriptor() } + } + +public val DeclarationDescriptorWithVisibility.isEffectivelyPublicApi: Boolean + get() { + var parent: DeclarationDescriptorWithVisibility? = this + + while (parent != null) { + if (!parent!!.getVisibility().isPublicAPI()) return false + + parent = DescriptorUtils.getParentOfType(parent, javaClass()) + } + + return true } \ No newline at end of file diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/TopDownAnalyzerFacadeForJS.java b/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/TopDownAnalyzerFacadeForJS.java index f8a623aa857..1b7d7260f86 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/TopDownAnalyzerFacadeForJS.java +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/TopDownAnalyzerFacadeForJS.java @@ -72,7 +72,7 @@ public final class TopDownAnalyzerFacadeForJS { ? new BindingTraceContext() : new DelegatingBindingTrace(libraryContext, "trace with preanalyzed library"); - ModuleDescriptorImpl module = createJsModule(""); + ModuleDescriptorImpl module = createJsModule("<" + config.getModuleId() + ">"); module.addDependencyOnModule(module); module.addDependencyOnModule(KotlinBuiltIns.getInstance().getBuiltInsModule()); ModuleDescriptor libraryModule = config.getLibraryModule(); diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/collectors/FunctionCollector.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/collectors/FunctionCollector.kt index 27e262a11e8..c0e178dd1fb 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/collectors/FunctionCollector.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/collectors/FunctionCollector.kt @@ -16,11 +16,8 @@ package org.jetbrains.kotlin.js.inline.util.collectors -import com.google.dart.compiler.backend.js.ast.RecursiveJsVisitor -import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer -import com.google.dart.compiler.backend.js.ast.JsNameRef -import com.google.dart.compiler.backend.js.ast.JsFunction -import com.google.dart.compiler.backend.js.ast.JsName +import com.google.dart.compiler.backend.js.ast.* +import org.jetbrains.kotlin.js.translate.expression.InlineMetadata import java.util.IdentityHashMap @@ -30,16 +27,18 @@ class FunctionCollector : RecursiveJsVisitor() { override fun visitPropertyInitializer(x: JsPropertyInitializer?) { super.visitPropertyInitializer(x) - val label = x?.getLabelExpr() + val label = x?.getLabelExpr() as? JsNameRef + val name = label?.getName() + if (name == null) return + val value = x?.getValueExpr() + val function = when (value) { + is JsFunction -> value + else -> InlineMetadata.decompose(value)?.function + } - if (label is JsNameRef && value is JsFunction) { - val name = label.getName() - val function = value as JsFunction - - if (name != null) { - functions[name] = function - } + if (function is JsFunction) { + functions[name] = function } } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java index a48e527611f..26556025216 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java @@ -17,15 +17,22 @@ package org.jetbrains.kotlin.js.translate.context; import com.google.dart.compiler.backend.js.ast.*; +import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; +import org.jetbrains.kotlin.descriptors.CallableDescriptor; import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.idea.JetLanguage; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.resolve.DescriptorUtils; +import java.util.Arrays; + import static com.google.dart.compiler.backend.js.ast.AstPackage.JsObjectScope; +import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getModuleName; import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getStableMangledNameForDescriptor; +import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getSuggestedName; +import static org.jetbrains.kotlin.resolve.DescriptorUtils.getFqNameSafe; /** * Encapsulates different types of constants and naming conventions. @@ -83,6 +90,10 @@ public final class Namer { private static final String PROTOTYPE_NAME = "prototype"; public static final String CAPTURED_VAR_FIELD = "v"; + public static final JsNameRef CREATE_INLINE_FUNCTION = new JsNameRef("defineInlineFunction", KOTLIN_OBJECT_REF); + private static final String INLINE_START_TAG = "inlineStartTag"; + private static final String INLINE_END_TAG = "inlineEndTag"; + @NotNull public static final JsExpression UNDEFINED_EXPRESSION = new JsPrefixOperation(JsUnaryOperator.VOID, JsNumberLiteral.ZERO); @@ -96,6 +107,27 @@ public final class Namer { return false; } + @NotNull + public static String getInlineStartTag(@NotNull CallableDescriptor functionDescriptor) { + return formatInlineTag(functionDescriptor, INLINE_START_TAG); + } + + @NotNull + public static String getInlineEndTag(@NotNull CallableDescriptor functionDescriptor) { + return formatInlineTag(functionDescriptor, INLINE_END_TAG); + } + + @NotNull + private static String formatInlineTag( + @NotNull CallableDescriptor functionDescriptor, + @NotNull String tag + ) { + FqName fqName = getFqNameSafe(functionDescriptor); + String mangledName = getSuggestedName(functionDescriptor); + String moduleName = getModuleName(functionDescriptor); + return StringUtil.join(Arrays.asList(tag, moduleName, fqName, mangledName), "."); + } + @NotNull public static String getReceiverParameterName() { return RECEIVER_PARAMETER_NAME; diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java index d99d0535965..0010bbdac4f 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java @@ -19,7 +19,6 @@ package org.jetbrains.kotlin.js.translate.context; import com.google.common.collect.Maps; import com.google.dart.compiler.backend.js.ast.*; import com.intellij.openapi.util.Factory; -import com.intellij.psi.PsiElement; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -40,12 +39,10 @@ import org.jetbrains.kotlin.types.reflect.ReflectionTypes; import java.util.Map; -import static org.jetbrains.kotlin.js.config.LibrarySourcesConfig.BUILTINS_JS_MODULE_NAME; import static org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.*; import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.*; import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getMangledName; import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getSuggestedName; -import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration; import static org.jetbrains.kotlin.resolve.DescriptorUtils.isExtension; /** @@ -486,22 +483,6 @@ public final class StaticContext { return JsAstUtils.replaceRootReference( result, new JsArrayAccess(namer.kotlin("modules"), program.getStringLiteral(moduleName))); } - - private String getExternalModuleName(DeclarationDescriptor descriptor) { - if (isBuiltin(descriptor)) return BUILTINS_JS_MODULE_NAME; - - PsiElement element = descriptorToDeclaration(descriptor); - if (element == null && descriptor instanceof PropertyAccessorDescriptor) { - element = descriptorToDeclaration(((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty()); - } - - if (element == null) { - ModuleDescriptor moduleDescriptor = DescriptorUtils.getContainingModule(descriptor); - String moduleName = moduleDescriptor.getName().asString(); - return moduleName.substring(1, moduleName.length()-1); - } - return element.getContainingFile().getUserData(LibrarySourcesConfig.EXTERNAL_MODULE_NAME); - } }; Rule constructorOrDefaultObjectHasTheSameQualifierAsTheClass = new Rule() { @Override diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.java index 678da192ba9..ec19c7f9db0 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.java @@ -17,18 +17,12 @@ package org.jetbrains.kotlin.js.translate.expression; -import com.google.dart.compiler.backend.js.ast.JsFunction; -import com.google.dart.compiler.backend.js.ast.JsName; -import com.google.dart.compiler.backend.js.ast.JsParameter; -import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer; +import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.backend.js.ast.metadata.MetadataPackage; import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; -import org.jetbrains.kotlin.descriptors.FunctionDescriptor; -import org.jetbrains.kotlin.descriptors.Modality; -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; +import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.js.translate.context.AliasingContext; import org.jetbrains.kotlin.js.translate.context.Namer; import org.jetbrains.kotlin.js.translate.context.TranslationContext; @@ -41,10 +35,12 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils; import java.util.Collections; import java.util.List; +import static org.jetbrains.kotlin.js.translate.reference.CallExpressionTranslator.shouldBeInlined; 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.FunctionBodyTranslator.translateFunctionBody; import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.setParameters; +import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getIsEffectivelyPublicApi; public final class FunctionTranslator extends AbstractTranslator { @NotNull @@ -101,6 +97,12 @@ public final class FunctionTranslator extends AbstractTranslator { public JsPropertyInitializer translateAsMethod() { JsName functionName = context().getNameForDescriptor(descriptor); generateFunctionObject(); + + if (shouldBeInlined(descriptor) && getIsEffectivelyPublicApi(descriptor)) { + InlineMetadata metadata = InlineMetadata.compose(functionObject, descriptor); + return new JsPropertyInitializer(functionName.makeRef(), metadata.getFunctionWithMetadata()); + } + return new JsPropertyInitializer(functionName.makeRef(), functionObject); } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/InlineMetadata.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/InlineMetadata.kt new file mode 100644 index 00000000000..ccf15875156 --- /dev/null +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/InlineMetadata.kt @@ -0,0 +1,107 @@ +/* + * 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.expression + +import com.google.dart.compiler.backend.js.ast.* +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.js.translate.context.Namer +import org.jetbrains.kotlin.js.translate.context.TranslationContext +import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.* + +import kotlin.platform.platformStatic + +private val METADATA_PROPERTIES_COUNT = 3 + +public class InlineMetadata( + val startTag: JsStringLiteral, + val function: JsFunction, + val endTag: JsStringLiteral +) { + class object { + platformStatic + fun compose(function: JsFunction, descriptor: CallableDescriptor): InlineMetadata { + val program = function.getScope().getProgram() + val startTag = program.getStringLiteral(Namer.getInlineStartTag(descriptor)) + val endTag = program.getStringLiteral(Namer.getInlineEndTag(descriptor)) + return InlineMetadata(startTag, function, endTag) + } + + /** + * Reads metadata from expression. + * + * To read metadata from source one needs to: + * 1. find index of startTag and endTag in source; + * 2. parse substring between startTagIndex - 1 (for opening quote) + * and endTagIndex + endTag.length() + 1 (for closing quote) + * 3. call InlineMetadata#decompose on resulting expression + * + * @see Namer#getInlineStartTag + * @see Namer#getInlineEndTag + * @see com.google.gwt.dev.js.JsParser + */ + platformStatic + fun decompose(expression: JsExpression?): InlineMetadata? = + when (expression) { + is JsBinaryOperation -> decomposeCommaExpression(expression) + is JsInvocation -> decomposeCreateFunctionCall(expression) + else -> null + } + + private fun decomposeCreateFunctionCall(call: JsInvocation): InlineMetadata? { + if (Namer.CREATE_INLINE_FUNCTION != call.getQualifier()) return null + + return decomposePropertiesList(call.getArguments()) + } + + private fun decomposeCommaExpression(expression: JsExpression): InlineMetadata? { + val properties = arrayListOf() + var decomposable: JsExpression? = expression + + while (decomposable is JsExpression) { + val binOp = decomposable as? JsBinaryOperation + + if (JsBinaryOperator.COMMA == binOp?.getOperator()) { + properties.add(binOp?.getArg2()) + decomposable = binOp?.getArg1() + } else { + properties.add(decomposable) + break + } + } + + return decomposePropertiesList(properties.reverse()) + } + + private fun decomposePropertiesList(properties: List): InlineMetadata? { + if (properties.size() != METADATA_PROPERTIES_COUNT) return null + + val startTag = properties[0] as? JsStringLiteral + val function = properties[1] as? JsFunction + val endTag = properties[2] as? JsStringLiteral + + if (startTag == null || function == null || endTag == null) return null + + return InlineMetadata(startTag, function, endTag) + } + } + + public val functionWithMetadata: JsExpression + get() { + val propertiesList = listOf(startTag, function, endTag) + return JsInvocation(Namer.CREATE_INLINE_FUNCTION, propertiesList) + } +} \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallExpressionTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallExpressionTranslator.java index daf678de689..519207c54eb 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallExpressionTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallExpressionTranslator.java @@ -89,6 +89,10 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl descriptor = resolvedCall.getCandidateDescriptor(); } + return shouldBeInlined(descriptor); + } + + public static boolean shouldBeInlined(@NotNull CallableDescriptor descriptor) { if (descriptor instanceof SimpleFunctionDescriptor) { return ((SimpleFunctionDescriptor) descriptor).getInlineStrategy().isInline(); } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java index 4b2b1491762..4197d2f3b5e 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java @@ -17,11 +17,13 @@ package org.jetbrains.kotlin.js.translate.utils; import com.intellij.openapi.util.Condition; +import com.intellij.psi.PsiElement; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.js.config.LibrarySourcesConfig; import org.jetbrains.kotlin.js.descriptorUtils.DescriptorUtilsPackage; import org.jetbrains.kotlin.js.translate.context.TranslationContext; import org.jetbrains.kotlin.name.Name; @@ -37,7 +39,9 @@ import java.util.Collection; import java.util.List; import java.util.Set; +import static org.jetbrains.kotlin.js.config.LibrarySourcesConfig.BUILTINS_JS_MODULE_NAME; import static org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isNativeObject; +import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration; import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; public final class JsDescriptorUtils { @@ -161,4 +165,32 @@ public final class JsDescriptorUtils { JetType type = context.bindingContext().get(BindingContext.EXPRESSION_TYPE, expression); return type != null ? DescriptorUtilsPackage.getNameIfStandardType(type) : null; } + + @NotNull + public static String getModuleName(@NotNull DeclarationDescriptor descriptor) { + String externalModuleName = getExternalModuleName(descriptor); + if (externalModuleName != null) return externalModuleName; + + return getModuleNameFromDescriptorName(descriptor); + } + + @Nullable + public static String getExternalModuleName(@NotNull DeclarationDescriptor descriptor) { + if (isBuiltin(descriptor)) return BUILTINS_JS_MODULE_NAME; + + PsiElement element = descriptorToDeclaration(descriptor); + if (element == null && descriptor instanceof PropertyAccessorDescriptor) { + element = descriptorToDeclaration(((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty()); + } + + if (element == null) return getModuleNameFromDescriptorName(descriptor); + + return element.getContainingFile().getUserData(LibrarySourcesConfig.EXTERNAL_MODULE_NAME); + } + + private static String getModuleNameFromDescriptorName(DeclarationDescriptor descriptor) { + ModuleDescriptor moduleDescriptor = DescriptorUtils.getContainingModule(descriptor); + String moduleName = moduleDescriptor.getName().asString(); + return moduleName.substring(1, moduleName.length() - 1); + } } diff --git a/js/js.translator/testData/kotlin_lib_ecma5.js b/js/js.translator/testData/kotlin_lib_ecma5.js index 00a40de6254..85993297036 100644 --- a/js/js.translator/testData/kotlin_lib_ecma5.js +++ b/js/js.translator/testData/kotlin_lib_ecma5.js @@ -475,4 +475,8 @@ var Kotlin = {}; Object.defineProperty(Kotlin.modules, id, {value: declaration}); }; + Kotlin.defineInlineFunction = function(startTag, fun, metadataArgs) { + return fun; + }; + })(Kotlin);