[JS] JsExport diagnostics and legacy support
Account for JsExport in legacy backend namer. It means we catch overloaded exported function conflicts for free! Add error diagnostics: * NESTED_JS_EXPORT (Fixes KT-36798) * WRONG_EXPORTED_DECLARATION (Part of the fix for KT-37752) * NON_EXPORTABLE_TYPE (Fixes KT-37771)
This commit is contained in:
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.getNameForAnnotatedObject
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isNativeObject
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
|
||||
@@ -40,7 +41,7 @@ import kotlin.math.abs
|
||||
* A new instance of this class can be created for each request, however, it's recommended to use stable instance, since
|
||||
* [NameSuggestion] supports caching.
|
||||
*/
|
||||
class NameSuggestion {
|
||||
class NameSuggestion(val bindingContext: BindingContext) {
|
||||
private val cache: MutableMap<DeclarationDescriptor, SuggestedName?> = Collections.synchronizedMap(WeakHashMap())
|
||||
|
||||
/**
|
||||
@@ -112,7 +113,7 @@ class NameSuggestion {
|
||||
// Local functions and variables are always private with their own names as suggested names
|
||||
is CallableDescriptor ->
|
||||
if (DescriptorUtils.isDescriptorWithLocalVisibility(descriptor)) {
|
||||
val ownName = getNameForAnnotatedObject(descriptor) ?: getSuggestedName(descriptor)
|
||||
val ownName = getNameForAnnotatedObject(descriptor, bindingContext) ?: getSuggestedName(descriptor)
|
||||
var name = ownName
|
||||
var scope = descriptor.containingDeclaration
|
||||
|
||||
@@ -195,7 +196,7 @@ class NameSuggestion {
|
||||
|
||||
parts.reverse()
|
||||
val unmangledName = parts.joinToString("$")
|
||||
val (id, stable) = mangleNameIfNecessary(unmangledName, fixedDescriptor)
|
||||
val (id, stable) = mangleNameIfNecessary(unmangledName, fixedDescriptor, bindingContext)
|
||||
return SuggestedName(listOf(id), stable, fixedDescriptor, current)
|
||||
}
|
||||
|
||||
@@ -217,7 +218,7 @@ class NameSuggestion {
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun mangleNameIfNecessary(baseName: String, descriptor: DeclarationDescriptor): NameAndStability {
|
||||
private fun mangleNameIfNecessary(baseName: String, descriptor: DeclarationDescriptor, bindingContext: BindingContext): NameAndStability {
|
||||
// If we have a callable descriptor (property or method) it can override method in a parent class.
|
||||
// Traverse to the topmost overridden method.
|
||||
// It does not matter which path to choose during traversal, since front-end must ensure
|
||||
@@ -230,7 +231,7 @@ class NameSuggestion {
|
||||
}
|
||||
|
||||
// If declaration is marked with either external, @native, @library or @JsName, return its stable name as is.
|
||||
val nativeName = getNameForAnnotatedObject(overriddenDescriptor)
|
||||
val nativeName = getNameForAnnotatedObject(overriddenDescriptor, bindingContext)
|
||||
if (nativeName != null) return NameAndStability(nativeName, true)
|
||||
|
||||
if (overriddenDescriptor is FunctionDescriptor) {
|
||||
|
||||
@@ -31,11 +31,13 @@ import org.jetbrains.kotlin.types.DynamicTypesAllowed
|
||||
object JsPlatformConfigurator : PlatformConfiguratorBase(
|
||||
DynamicTypesAllowed(),
|
||||
additionalDeclarationCheckers = listOf(
|
||||
NativeInvokeChecker(), NativeGetterChecker(), NativeSetterChecker(),
|
||||
JsNameChecker, JsModuleChecker, JsExternalFileChecker,
|
||||
JsExternalChecker, JsInheritanceChecker, JsMultipleInheritanceChecker,
|
||||
JsRuntimeAnnotationChecker,
|
||||
JsDynamicDeclarationChecker
|
||||
NativeInvokeChecker(), NativeGetterChecker(), NativeSetterChecker(),
|
||||
JsNameChecker, JsModuleChecker, JsExternalFileChecker,
|
||||
JsExternalChecker, JsInheritanceChecker, JsMultipleInheritanceChecker,
|
||||
JsRuntimeAnnotationChecker,
|
||||
JsDynamicDeclarationChecker,
|
||||
JsExportAnnotationChecker,
|
||||
JsExportDeclarationChecker
|
||||
),
|
||||
additionalCallCheckers = listOf(
|
||||
JsModuleCallChecker,
|
||||
@@ -46,7 +48,6 @@ object JsPlatformConfigurator : PlatformConfiguratorBase(
|
||||
identifierChecker = JsIdentifierChecker
|
||||
) {
|
||||
override fun configureModuleComponents(container: StorageComponentContainer) {
|
||||
container.useInstance(NameSuggestion())
|
||||
container.useImpl<JsCallChecker>()
|
||||
container.useImpl<JsTypeSpecificityComparator>()
|
||||
container.useImpl<JsNameClashChecker>()
|
||||
|
||||
+4
@@ -100,6 +100,10 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy {
|
||||
"Can't apply multiple inheritance here, since it's impossible to generate bridge for system function {0}",
|
||||
Renderers.DECLARATION_NAME_WITH_KIND)
|
||||
|
||||
put(ErrorsJs.NESTED_JS_EXPORT, "@JsExport is only allowed on files and top-level declarations")
|
||||
put(ErrorsJs.WRONG_EXPORTED_DECLARATION, "Declaration of such kind ({0}) can't be exported to JS", Renderers.STRING)
|
||||
put(ErrorsJs.NON_EXPORTABLE_TYPE, "Exported declaration uses non-exportable {0} type: {1}", Renderers.STRING, RENDER_TYPE)
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +105,10 @@ public interface ErrorsJs {
|
||||
DiagnosticFactory1<PsiElement, CallableMemberDescriptor> WRONG_MULTIPLE_INHERITANCE =
|
||||
DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
|
||||
DiagnosticFactory0<PsiElement> NESTED_JS_EXPORT = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<KtExpression, String> WRONG_EXPORTED_DECLARATION = DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
DiagnosticFactory2<PsiElement, String, KotlinType> NON_EXPORTABLE_TYPE = DiagnosticFactory2.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
Object _initializer = new Object() {
|
||||
{
|
||||
|
||||
+2
-1
@@ -25,8 +25,9 @@ import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
|
||||
class JsBuiltinNameClashChecker(private val nameSuggestion: NameSuggestion) : DeclarationChecker {
|
||||
class JsBuiltinNameClashChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
val nameSuggestion = NameSuggestion(context.trace.bindingContext)
|
||||
if (AnnotationsUtils.isNativeObject(descriptor)) return
|
||||
if (descriptor.containingDeclaration !is ClassDescriptor) return
|
||||
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.resolve.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
|
||||
object JsExportAnnotationChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
val trace = context.trace
|
||||
|
||||
val jsExport = AnnotationsUtils.getJsExportAnnotation(descriptor) ?: return
|
||||
val jsExportPsi = jsExport.source.getPsi() ?: declaration
|
||||
|
||||
if (descriptor !is PackageFragmentDescriptor && !DescriptorUtils.isTopLevelDeclaration(descriptor)) {
|
||||
trace.report(ErrorsJs.NESTED_JS_EXPORT.on(jsExportPsi))
|
||||
}
|
||||
}
|
||||
}
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.resolve.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind.*
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty
|
||||
import org.jetbrains.kotlin.resolve.inline.isInlineWithReified
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeProjection
|
||||
import org.jetbrains.kotlin.types.isDynamic
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
|
||||
object JsExportDeclarationChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
val trace = context.trace
|
||||
val bindingContext = trace.bindingContext
|
||||
|
||||
fun checkTypeParameter(descriptor: TypeParameterDescriptor) {
|
||||
for (upperBound in descriptor.upperBounds) {
|
||||
if (!isTypeExportable(upperBound, bindingContext)) {
|
||||
val typeParameterDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor)!!
|
||||
trace.report(ErrorsJs.NON_EXPORTABLE_TYPE.on(typeParameterDeclaration, "upper bound", upperBound))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun checkValueParameter(descriptor: ValueParameterDescriptor) {
|
||||
if (!isTypeExportable(descriptor.type, bindingContext)) {
|
||||
val valueParameterDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor)!!
|
||||
trace.report(ErrorsJs.NON_EXPORTABLE_TYPE.on(valueParameterDeclaration, "parameter", descriptor.type))
|
||||
}
|
||||
}
|
||||
|
||||
if (!AnnotationsUtils.isExportedObject(descriptor, bindingContext)) return
|
||||
if (descriptor !is MemberDescriptor)
|
||||
return
|
||||
|
||||
val hasJsName = AnnotationsUtils.getJsNameAnnotation(descriptor) != null
|
||||
|
||||
fun reportWrongExportedDeclaration(kind: String) {
|
||||
trace.report(ErrorsJs.WRONG_EXPORTED_DECLARATION.on(declaration, kind))
|
||||
}
|
||||
|
||||
if (descriptor.isExpect) {
|
||||
reportWrongExportedDeclaration("expect")
|
||||
}
|
||||
|
||||
when (descriptor) {
|
||||
is FunctionDescriptor -> {
|
||||
for (typeParameter in descriptor.typeParameters) {
|
||||
checkTypeParameter(typeParameter)
|
||||
}
|
||||
|
||||
if (descriptor.isInlineWithReified()) {
|
||||
reportWrongExportedDeclaration("inline function with reified type parameters")
|
||||
return
|
||||
}
|
||||
|
||||
if (descriptor.isSuspend) {
|
||||
reportWrongExportedDeclaration("suspend function")
|
||||
return
|
||||
}
|
||||
|
||||
if (descriptor is ConstructorDescriptor) {
|
||||
if (!descriptor.isPrimary && !hasJsName)
|
||||
reportWrongExportedDeclaration("secondary constructor without @JsName")
|
||||
}
|
||||
|
||||
// Properties are checked instead of property accessors
|
||||
if (descriptor !is PropertyAccessorDescriptor) {
|
||||
for (parameter in descriptor.valueParameters) {
|
||||
checkValueParameter(parameter)
|
||||
}
|
||||
|
||||
descriptor.returnType?.let { returnType ->
|
||||
if (!isTypeExportable(returnType, bindingContext, true)) {
|
||||
trace.report(ErrorsJs.NON_EXPORTABLE_TYPE.on(declaration, "return", returnType))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is PropertyDescriptor -> {
|
||||
if (descriptor.isExtensionProperty) {
|
||||
reportWrongExportedDeclaration("extension property")
|
||||
return
|
||||
}
|
||||
if (!isTypeExportable(descriptor.type, bindingContext)) {
|
||||
trace.report(ErrorsJs.NON_EXPORTABLE_TYPE.on(declaration, "property", descriptor.type))
|
||||
}
|
||||
}
|
||||
|
||||
is ClassDescriptor -> {
|
||||
for (typeParameter in descriptor.declaredTypeParameters) {
|
||||
checkTypeParameter(typeParameter)
|
||||
}
|
||||
|
||||
if (descriptor.kind == ENUM_CLASS) {
|
||||
reportWrongExportedDeclaration("enum class")
|
||||
return
|
||||
}
|
||||
if (descriptor.kind == ANNOTATION_CLASS) {
|
||||
reportWrongExportedDeclaration("annotation class")
|
||||
return
|
||||
}
|
||||
if (descriptor.kind == ENUM_ENTRY) {
|
||||
// Covered by ENUM_CLASS
|
||||
return
|
||||
}
|
||||
|
||||
for (superType in descriptor.defaultType.supertypes()) {
|
||||
if (!isTypeExportable(superType, bindingContext)) {
|
||||
trace.report(ErrorsJs.NON_EXPORTABLE_TYPE.on(declaration, "super", superType))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun isTypeExportable(type: KotlinType, bindingContext: BindingContext, isReturnType: Boolean = false): Boolean {
|
||||
if (isReturnType && type.isUnit())
|
||||
return true
|
||||
|
||||
if (type.isFunctionType) {
|
||||
val arguments = type.arguments
|
||||
val argumentsSize = type.arguments.size - 1
|
||||
for (i in 0 until argumentsSize) {
|
||||
if (!isTypeExportable(arguments[i].type, bindingContext))
|
||||
return false
|
||||
}
|
||||
if (!isTypeExportable(arguments.last().type, bindingContext, isReturnType = true))
|
||||
return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
for (argument: TypeProjection in type.arguments) {
|
||||
if (!isTypeExportable(argument.type, bindingContext))
|
||||
return false
|
||||
}
|
||||
|
||||
val nonNullable = type.makeNotNullable()
|
||||
|
||||
// Is primitive exportable type
|
||||
if (nonNullable.isAnyOrNullableAny() ||
|
||||
nonNullable.isDynamic() ||
|
||||
nonNullable.isBoolean() ||
|
||||
KotlinBuiltIns.isThrowableOrNullableThrowable(nonNullable) ||
|
||||
KotlinBuiltIns.isString(nonNullable) ||
|
||||
(nonNullable.isPrimitiveNumberOrNullableType() && !nonNullable.isLong()) ||
|
||||
nonNullable.isNothingOrNullableNothing() ||
|
||||
(KotlinBuiltIns.isArray(type)) ||
|
||||
KotlinBuiltIns.isPrimitiveArray(type)
|
||||
) return true
|
||||
|
||||
val descriptor: ClassifierDescriptor = type.constructor.declarationDescriptor ?: return false
|
||||
return descriptor.isEffectivelyExternal() || AnnotationsUtils.isExportedObject(descriptor, bindingContext)
|
||||
}
|
||||
}
|
||||
+13
-2
@@ -5,18 +5,29 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.resolve.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
||||
import org.jetbrains.kotlin.js.naming.NameSuggestion
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
|
||||
class JsNameCharsChecker(private val suggestion: NameSuggestion) : DeclarationChecker {
|
||||
class JsNameCharsChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
val bindingContext = context.trace.bindingContext
|
||||
|
||||
if (descriptor is PropertyAccessorDescriptor && AnnotationsUtils.getJsName(descriptor) == null) return
|
||||
|
||||
// This case will be reported as WRONG_EXPORTED_DECLARATION for
|
||||
// secondary constructor with missing JsName. Skipping it here to simplify further logic.
|
||||
if (descriptor is ConstructorDescriptor &&
|
||||
AnnotationsUtils.getJsName(descriptor) == null &&
|
||||
AnnotationsUtils.isExportedObject(descriptor, bindingContext)
|
||||
) return
|
||||
|
||||
val suggestion = NameSuggestion(bindingContext)
|
||||
val suggestedName = suggestion.suggest(descriptor) ?: return
|
||||
if (suggestedName.stable && suggestedName.names.any { NameSuggestion.sanitizeName(it) != it }) {
|
||||
context.trace.report(ErrorsJs.NAME_CONTAINS_ILLEGAL_CHARS.on(declaration))
|
||||
|
||||
+3
-1
@@ -35,7 +35,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
|
||||
class JsNameClashChecker(
|
||||
private val nameSuggestion: NameSuggestion,
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
) : DeclarationChecker {
|
||||
companion object {
|
||||
@@ -45,6 +44,7 @@ class JsNameClashChecker(
|
||||
Errors.PACKAGE_OR_CLASSIFIER_REDECLARATION)
|
||||
}
|
||||
|
||||
lateinit var nameSuggestion: NameSuggestion
|
||||
private val scopes = mutableMapOf<DeclarationDescriptor, MutableMap<String, DeclarationDescriptor>>()
|
||||
private val clashedFakeOverrides = mutableMapOf<DeclarationDescriptor, Pair<DeclarationDescriptor, DeclarationDescriptor>>()
|
||||
private val clashedDescriptors = mutableSetOf<Pair<DeclarationDescriptor, String>>()
|
||||
@@ -62,6 +62,8 @@ class JsNameClashChecker(
|
||||
diagnosticHolder: DiagnosticSink, bindingContext: BindingContext
|
||||
) {
|
||||
if (descriptor is ConstructorDescriptor && descriptor.isPrimary) return
|
||||
if (!this::nameSuggestion.isInitialized || nameSuggestion.bindingContext !== bindingContext)
|
||||
nameSuggestion = NameSuggestion(bindingContext)
|
||||
|
||||
for (suggested in nameSuggestion.suggestAllPossibleNames(descriptor)) {
|
||||
if (suggested.stable && suggested.scope is ClassOrPackageFragmentDescriptor && presentsInGeneratedCode(suggested.descriptor)) {
|
||||
|
||||
@@ -40,6 +40,7 @@ import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.isEf
|
||||
|
||||
public final class AnnotationsUtils {
|
||||
private static final String JS_NAME = "kotlin.js.JsName";
|
||||
private static final FqName JS_EXPORT = new FqName("kotlin.js.JsExport");
|
||||
public static final FqName JS_MODULE_ANNOTATION = new FqName("kotlin.js.JsModule");
|
||||
private static final FqName JS_NON_MODULE_ANNOTATION = new FqName("kotlin.js.JsNonModule");
|
||||
public static final FqName JS_QUALIFIER_ANNOTATION = new FqName("kotlin.js.JsQualifier");
|
||||
@@ -83,7 +84,10 @@ public final class AnnotationsUtils {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getNameForAnnotatedObject(@NotNull DeclarationDescriptor descriptor) {
|
||||
public static String getNameForAnnotatedObject(
|
||||
@NotNull DeclarationDescriptor descriptor,
|
||||
@NotNull BindingContext bindingContext
|
||||
) {
|
||||
String defaultJsName = getJsName(descriptor);
|
||||
|
||||
for (PredefinedAnnotation annotation : PredefinedAnnotation.Companion.getWITH_CUSTOM_NAME()) {
|
||||
@@ -97,7 +101,7 @@ public final class AnnotationsUtils {
|
||||
return name != null ? name : descriptor.getName().asString();
|
||||
}
|
||||
|
||||
if (defaultJsName == null && isEffectivelyExternalMember(descriptor)) {
|
||||
if (defaultJsName == null && (isEffectivelyExternalMember(descriptor) || isExportedObject(descriptor, bindingContext))) {
|
||||
return descriptor.getName().asString();
|
||||
}
|
||||
|
||||
@@ -112,6 +116,23 @@ public final class AnnotationsUtils {
|
||||
return descriptor.getAnnotations().findAnnotation(annotation.getFqName());
|
||||
}
|
||||
|
||||
public static boolean isExportedObject(@NotNull DeclarationDescriptor descriptor, @NotNull BindingContext bindingContext) {
|
||||
if (descriptor instanceof MemberDescriptor) {
|
||||
MemberDescriptor memberDescriptor = (MemberDescriptor) descriptor;
|
||||
if (memberDescriptor.getVisibility() != Visibilities.PUBLIC) return false;
|
||||
}
|
||||
|
||||
if (hasAnnotationOrInsideAnnotatedClass(descriptor, JS_EXPORT)) return true;
|
||||
|
||||
if (CollectionsKt.any(getContainingFileAnnotations(bindingContext, descriptor), annotation ->
|
||||
JS_EXPORT.equals(annotation.getFqName())
|
||||
)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isNativeObject(@NotNull DeclarationDescriptor descriptor) {
|
||||
if (hasAnnotationOrInsideAnnotatedClass(descriptor, PredefinedAnnotation.NATIVE) || isEffectivelyExternalMember(descriptor)) return true;
|
||||
|
||||
@@ -154,6 +175,11 @@ public final class AnnotationsUtils {
|
||||
return descriptor.getAnnotations().findAnnotation(new FqName(JS_NAME));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AnnotationDescriptor getJsExportAnnotation(@NotNull DeclarationDescriptor descriptor) {
|
||||
return descriptor.getAnnotations().findAnnotation(JS_EXPORT);
|
||||
}
|
||||
|
||||
public static boolean isPredefinedObject(@NotNull DeclarationDescriptor descriptor) {
|
||||
if (descriptor instanceof MemberDescriptor && ((MemberDescriptor) descriptor).isExpect()) return true;
|
||||
if (isEffectivelyExternalMember(descriptor)) return true;
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.expression.InlineMetadata
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getModuleName
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||
import org.jetbrains.kotlin.utils.JsLibraryUtils
|
||||
import java.io.File
|
||||
@@ -55,7 +56,8 @@ private val SPECIAL_FUNCTION_PATTERN = Regex("var\\s+($JS_IDENTIFIER)\\s*=\\s*($
|
||||
|
||||
class FunctionReader(
|
||||
private val reporter: JsConfig.Reporter,
|
||||
private val config: JsConfig
|
||||
private val config: JsConfig,
|
||||
private val bindingContext: BindingContext
|
||||
) {
|
||||
/**
|
||||
* fileContent: .js file content, that contains this module definition.
|
||||
@@ -205,7 +207,7 @@ class FunctionReader(
|
||||
info: ModuleInfo,
|
||||
fragment: JsProgramFragment
|
||||
): FunctionWithWrapper {
|
||||
val tag = Namer.getFunctionTag(descriptor, config)
|
||||
val tag = Namer.getFunctionTag(descriptor, config, bindingContext)
|
||||
val moduleReference = fragment.inlineModuleMap[tag]?.deepCopy() ?: fragment.scope.declareName("_").makeRef()
|
||||
val allDefinedNames = collectDefinedNamesInAllScopes(fn.function)
|
||||
val replacements = hashMapOf(
|
||||
@@ -234,7 +236,7 @@ class FunctionReader(
|
||||
|
||||
private fun readFunctionFromSource(descriptor: CallableDescriptor, info: ModuleInfo): FunctionWithWrapper? {
|
||||
val source = info.fileContent
|
||||
var tag = Namer.getFunctionTag(descriptor, config)
|
||||
var tag = Namer.getFunctionTag(descriptor, config, bindingContext)
|
||||
var index = source.indexOf(tag)
|
||||
|
||||
// Hack for compatibility with old versions of stdlib
|
||||
|
||||
@@ -13,11 +13,13 @@ import org.jetbrains.kotlin.js.inline.context.FunctionDefinitionLoader
|
||||
import org.jetbrains.kotlin.js.inline.context.InliningContext
|
||||
|
||||
import org.jetbrains.kotlin.js.translate.general.AstGenerationResult
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
class JsInliner(
|
||||
val reporter: JsConfig.Reporter,
|
||||
val config: JsConfig,
|
||||
val trace: DiagnosticSink,
|
||||
val bindingContext: BindingContext,
|
||||
val translationResult: AstGenerationResult
|
||||
) {
|
||||
|
||||
|
||||
+3
-3
@@ -75,7 +75,7 @@ class FunctionDefinitionLoader(
|
||||
return lookUpFunctionDirect(call, scope) ?: lookUpFunctionIndirect(call, scope) ?: lookUpFunctionExternal(call, scope.fragment)
|
||||
}
|
||||
|
||||
private val functionReader = FunctionReader(inliner.reporter, inliner.config)
|
||||
private val functionReader = FunctionReader(inliner.reporter, inliner.config, inliner.bindingContext)
|
||||
|
||||
private data class FragmentInfo(
|
||||
val functions: Map<JsName, FunctionWithWrapper>,
|
||||
@@ -160,7 +160,7 @@ class FunctionDefinitionLoader(
|
||||
private fun lookUpFunctionDirect(call: JsInvocation, callsiteScope: InliningScope): InlineFunctionDefinition? {
|
||||
val descriptor = call.descriptor ?: return null
|
||||
|
||||
val tag = Namer.getFunctionTag(descriptor, inliner.config)
|
||||
val tag = Namer.getFunctionTag(descriptor, inliner.config, inliner.bindingContext)
|
||||
|
||||
val definitionFragment = fragmentByTag(tag) ?: return null
|
||||
|
||||
@@ -178,7 +178,7 @@ class FunctionDefinitionLoader(
|
||||
private fun lookUpFunctionExternal(call: JsInvocation, fragment: JsProgramFragment): InlineFunctionDefinition? =
|
||||
call.descriptor?.let { descriptor ->
|
||||
functionReader[descriptor, fragment]?.let {
|
||||
InlineFunctionDefinition(it, Namer.getFunctionTag(descriptor, inliner.config))
|
||||
InlineFunctionDefinition(it, Namer.getFunctionTag(descriptor, inliner.config, inliner.bindingContext))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,11 @@ fun main(args: Array<String>) {
|
||||
model("typescript-export/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS_IR)
|
||||
}
|
||||
|
||||
testClass<AbstractLegacyJsTypeScriptExportTest> {
|
||||
model("typescript-export/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS)
|
||||
}
|
||||
|
||||
|
||||
testClass<AbstractSourceMapGenerationSmokeTest> {
|
||||
model("sourcemap/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS)
|
||||
}
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.test.semantics
|
||||
|
||||
import org.jetbrains.kotlin.js.test.BasicBoxTest
|
||||
|
||||
abstract class AbstractLegacyJsTypeScriptExportTest : BasicBoxTest(
|
||||
pathToTestDir = TEST_DATA_DIR_PATH + "typescript-export/",
|
||||
testGroupOutputDirPrefix = "legacy-typescript-export/",
|
||||
pathToRootOutputDir = TEST_DATA_DIR_PATH
|
||||
)
|
||||
Generated
+139
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.test.semantics;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TargetBackend;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("js/js.translator/testData/typescript-export")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class LegacyJsTypeScriptExportTestGenerated extends AbstractLegacyJsTypeScriptExportTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInTypescript_export() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/declarations")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Declarations extends AbstractLegacyJsTypeScriptExportTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInDeclarations() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/declarations"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("declarations.kt")
|
||||
public void testDeclarations() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/declarations/declarations.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/inheritance")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Inheritance extends AbstractLegacyJsTypeScriptExportTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInInheritance() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/inheritance"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("inheritance.kt")
|
||||
public void testInheritance() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/inheritance/inheritance.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/namespaces")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Namespaces extends AbstractLegacyJsTypeScriptExportTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInNamespaces() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/namespaces"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("namespaces.kt")
|
||||
public void testNamespaces() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/namespaces/namespaces.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/primitives")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Primitives extends AbstractLegacyJsTypeScriptExportTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInPrimitives() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/primitives"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("primitives.kt")
|
||||
public void testPrimitives() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/primitives/primitives.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/selectiveExport")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class SelectiveExport extends AbstractLegacyJsTypeScriptExportTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInSelectiveExport() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/selectiveExport"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("selectiveExport.kt")
|
||||
public void testSelectiveExport() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/selectiveExport/selectiveExport.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/visibility")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Visibility extends AbstractLegacyJsTypeScriptExportTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInVisibility() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/visibility"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("visibility.kt")
|
||||
public void testVisibility() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/visibility/visibility.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,6 +167,7 @@ class K2JSTranslator @JvmOverloads constructor(
|
||||
reporter,
|
||||
config,
|
||||
analysisResult.bindingTrace,
|
||||
bindingTrace.bindingContext,
|
||||
translationResult
|
||||
).process()
|
||||
if (hasError(diagnostics)) return TranslationResult.Fail(diagnostics)
|
||||
|
||||
@@ -34,12 +34,12 @@ import org.jetbrains.kotlin.js.backend.ast.metadata.TypeCheck;
|
||||
import org.jetbrains.kotlin.js.config.JsConfig;
|
||||
import org.jetbrains.kotlin.js.naming.NameSuggestion;
|
||||
import org.jetbrains.kotlin.js.naming.SuggestedName;
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices;
|
||||
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.ArrayFIF;
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -57,8 +57,8 @@ public final class Namer {
|
||||
public static final String KOTLIN_NAME = KotlinLanguage.NAME;
|
||||
public static final String KOTLIN_LOWER_NAME = KOTLIN_NAME.toLowerCase();
|
||||
|
||||
public static final String EQUALS_METHOD_NAME = getStableMangledNameForDescriptor(JsPlatformAnalyzerServices.INSTANCE.getBuiltIns().getAny(), "equals");
|
||||
public static final String COMPARE_TO_METHOD_NAME = getStableMangledNameForDescriptor(JsPlatformAnalyzerServices.INSTANCE.getBuiltIns().getComparable(), "compareTo");
|
||||
public static final String EQUALS_METHOD_NAME = "equals";
|
||||
public static final String COMPARE_TO_METHOD_NAME = "compareTo_11rb$";
|
||||
public static final String LONG_FROM_NUMBER = "fromNumber";
|
||||
public static final String LONG_TO_NUMBER = "toNumber";
|
||||
public static final String LONG_FROM_INT = "fromInt";
|
||||
@@ -134,7 +134,11 @@ public final class Namer {
|
||||
public static final String SAM_FIELD_NAME = "function$";
|
||||
|
||||
@NotNull
|
||||
public static String getFunctionTag(@NotNull CallableDescriptor functionDescriptor, @NotNull JsConfig config) {
|
||||
public static String getFunctionTag(
|
||||
@NotNull CallableDescriptor functionDescriptor,
|
||||
@NotNull JsConfig config,
|
||||
@NotNull BindingContext bindingContext
|
||||
) {
|
||||
String intrinsicTag = ArrayFIF.INSTANCE.getTag(functionDescriptor, config);
|
||||
if (intrinsicTag != null) return intrinsicTag;
|
||||
|
||||
@@ -147,7 +151,7 @@ public final class Namer {
|
||||
qualifier = fqNameParent.asString();
|
||||
}
|
||||
|
||||
SuggestedName suggestedName = new NameSuggestion().suggest(functionDescriptor);
|
||||
SuggestedName suggestedName = new NameSuggestion(bindingContext).suggest(functionDescriptor);
|
||||
assert suggestedName != null : "Suggested name can be null only for module descriptors: " + functionDescriptor;
|
||||
String mangledName = suggestedName.getNames().get(0);
|
||||
return StringUtil.join(Arrays.asList(moduleName, qualifier, mangledName), ".");
|
||||
@@ -225,18 +229,6 @@ public final class Namer {
|
||||
callSetProperty = kotlin("callSetter");
|
||||
}
|
||||
|
||||
// TODO: get rid of this function
|
||||
@NotNull
|
||||
private static String getStableMangledNameForDescriptor(@NotNull ClassDescriptor descriptor, @NotNull String functionName) {
|
||||
Collection<? extends SimpleFunctionDescriptor> functions = descriptor.getDefaultType().getMemberScope().getContributedFunctions(
|
||||
Name.identifier(functionName), NoLookupLocation.FROM_BACKEND
|
||||
);
|
||||
assert functions.size() == 1 : "Can't select a single function: " + functionName + " in " + descriptor;
|
||||
SuggestedName suggested = new NameSuggestion().suggest(functions.iterator().next());
|
||||
assert suggested != null : "Suggested name for class members is always non-null: " + functions.iterator().next();
|
||||
return suggested.getNames().get(0);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsNameRef kotlin(@NotNull JsName name) {
|
||||
return pureFqn(name, kotlinObject());
|
||||
|
||||
@@ -111,7 +111,7 @@ public final class StaticContext {
|
||||
private final JsImportedModule currentModuleAsImported;
|
||||
|
||||
@NotNull
|
||||
private final NameSuggestion nameSuggestion = new NameSuggestion();
|
||||
private final NameSuggestion nameSuggestion;
|
||||
|
||||
@NotNull
|
||||
private final Map<DeclarationDescriptor, JsName> nameCache = new HashMap<>();
|
||||
@@ -169,6 +169,7 @@ public final class StaticContext {
|
||||
fragment = new JsProgramFragment(rootFunction.getScope(), packageFqn);
|
||||
|
||||
this.bindingTrace = bindingTrace;
|
||||
this.nameSuggestion = new NameSuggestion(bindingTrace.getBindingContext());
|
||||
this.namer = Namer.newInstance(program.getRootScope());
|
||||
this.intrinsics = new Intrinsics();
|
||||
this.rootScope = fragment.getScope();
|
||||
@@ -801,7 +802,7 @@ public final class StaticContext {
|
||||
|
||||
public void addInlineCall(@NotNull CallableDescriptor descriptor) {
|
||||
descriptor = (CallableDescriptor) JsDescriptorUtils.findRealInlineDeclaration(descriptor);
|
||||
String tag = Namer.getFunctionTag(descriptor, config);
|
||||
String tag = Namer.getFunctionTag(descriptor, config, getBindingContext());
|
||||
JsExpression moduleExpression = exportModuleForInline(DescriptorUtils.getContainingModule(descriptor));
|
||||
if (moduleExpression == null) {
|
||||
moduleExpression = getModuleExpressionFor(descriptor);
|
||||
|
||||
+2
-2
@@ -179,13 +179,13 @@ public class TranslationContext {
|
||||
@NotNull
|
||||
public TranslationContext newFunctionBodyWithUsageTracker(@NotNull JsFunction fun, @NotNull MemberDescriptor descriptor) {
|
||||
DynamicContext dynamicContext = DynamicContext.newContext(fun.getScope(), fun.getBody());
|
||||
UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor);
|
||||
UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor, bindingContext());
|
||||
return new TranslationContext(this, this.staticContext, dynamicContext, this.aliasingContext.inner(), usageTracker, descriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TranslationContext innerWithUsageTracker(@NotNull MemberDescriptor descriptor) {
|
||||
UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor);
|
||||
UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor, bindingContext());
|
||||
return new TranslationContext(this, staticContext, dynamicContext, aliasingContext.inner(), usageTracker, descriptor);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.js.backend.ast.JsScope
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.descriptor
|
||||
import org.jetbrains.kotlin.js.descriptorUtils.isCoroutineLambda
|
||||
import org.jetbrains.kotlin.js.naming.NameSuggestion
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.*
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||
@@ -30,7 +31,8 @@ private val CAPTURED_RECEIVER_NAME_PREFIX : String = "this$"
|
||||
|
||||
class UsageTracker(
|
||||
private val parent: UsageTracker?,
|
||||
val containingDescriptor: MemberDescriptor
|
||||
val containingDescriptor: MemberDescriptor,
|
||||
val bindingContext: BindingContext
|
||||
) {
|
||||
|
||||
private val captured = linkedMapOf<DeclarationDescriptor, JsName>()
|
||||
@@ -175,7 +177,7 @@ class UsageTracker(
|
||||
|
||||
// Append 'closure$' prefix to avoid name clash between closure and member fields in case of local classes
|
||||
else -> {
|
||||
val mangled = NameSuggestion.sanitizeName(NameSuggestion().suggest(this)!!.names.last())
|
||||
val mangled = NameSuggestion.sanitizeName(NameSuggestion(bindingContext).suggest(this)!!.names.last())
|
||||
"closure\$$mangled"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class InlineMetadata(val tag: JsStringLiteral, val function: FunctionWithWrapper
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun compose(function: JsFunction, descriptor: CallableDescriptor, context: TranslationContext): InlineMetadata {
|
||||
val tag = JsStringLiteral(Namer.getFunctionTag(descriptor, context.config))
|
||||
val tag = JsStringLiteral(Namer.getFunctionTag(descriptor, context.config, context.bindingContext()))
|
||||
val inliningContext = context.inlineFunctionContext!!
|
||||
val block = JsBlock(inliningContext.importBlock.statements + inliningContext.prototypeBlock.statements +
|
||||
inliningContext.declarationsBlock.statements + JsReturn(function))
|
||||
|
||||
+3
-4
@@ -1,16 +1,15 @@
|
||||
// SKIP_MINIFICATION
|
||||
|
||||
// Exported declaration uses non-exportable return type: Char
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
@JsName("foo")
|
||||
@JsExport
|
||||
fun foo(): Char = '1'
|
||||
|
||||
@JsExport
|
||||
val p1: Char = '2'
|
||||
|
||||
@JsExport
|
||||
var p2: Char = '3'
|
||||
|
||||
@JsExport
|
||||
var p3: Char = '4'
|
||||
get() = field + 1
|
||||
set(value) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1276
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
@JsExport
|
||||
class A(val x: Char)
|
||||
|
||||
fun typeOf(x: dynamic): String = js("typeof x")
|
||||
|
||||
@@ -4,7 +4,6 @@ interface I {
|
||||
val a: Char
|
||||
}
|
||||
|
||||
@JsExport
|
||||
object X : I {
|
||||
override var a = '#'
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1289
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
@JsExport
|
||||
open class A {
|
||||
val foo: Char
|
||||
get() = 'X'
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1282
|
||||
|
||||
@JsExport
|
||||
interface I {
|
||||
fun ok(): String
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ class A {
|
||||
}
|
||||
}
|
||||
|
||||
@JsExport
|
||||
val A.z: Int
|
||||
@JsName("getZ_") get() = 42
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
|
||||
@file:JsExport
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
|
||||
@file:JsExport
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
|
||||
// FILE: file1.kt
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ declare namespace JS_TESTS {
|
||||
type Nullable<T> = T | null | undefined
|
||||
namespace foo {
|
||||
const _any: any;
|
||||
const _unit: void;
|
||||
function _nothing(): never
|
||||
const _throwable: Error;
|
||||
const _string: string;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
|
||||
@file:JsExport
|
||||
|
||||
@@ -8,8 +9,6 @@ package foo
|
||||
|
||||
val _any: Any = Any()
|
||||
|
||||
val _unit: Unit = Unit
|
||||
|
||||
fun _nothing(): Nothing { throw Throwable() }
|
||||
|
||||
val _throwable: Throwable = Throwable()
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
|
||||
// FILE: file1.kt
|
||||
package foo
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
|
||||
// TODO fix statics export in DCE-driven mode
|
||||
// SKIP_DCE_DRIVEN
|
||||
|
||||
Reference in New Issue
Block a user