mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-04-08 08:31:32 +00:00
Compare commits
97 Commits
rr/mitropo
...
build-1.4.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59183a8142 | ||
|
|
70ea53315d | ||
|
|
63d549dfa1 | ||
|
|
68e1acd2cb | ||
|
|
6410aed1b4 | ||
|
|
6393667dda | ||
|
|
5cad8a793c | ||
|
|
63575582c4 | ||
|
|
d5ffc7416d | ||
|
|
0ade8140f7 | ||
|
|
dbb47cf48e | ||
|
|
cd1bf563cd | ||
|
|
f0bc52222d | ||
|
|
8cb4f59114 | ||
|
|
743abea690 | ||
|
|
c3cbfe34c4 | ||
|
|
53b31a20ca | ||
|
|
94de114894 | ||
|
|
017f640f26 | ||
|
|
e93bcc55ae | ||
|
|
8bc4407be0 | ||
|
|
6c9c2a287d | ||
|
|
9c0b96af71 | ||
|
|
a150e7b6e5 | ||
|
|
929bb0e8d1 | ||
|
|
9d48ecfac3 | ||
|
|
b8f0ad2111 | ||
|
|
5bdf3d5757 | ||
|
|
477cca3c99 | ||
|
|
a98ad79d86 | ||
|
|
7a8908a75b | ||
|
|
a0cccdf75c | ||
|
|
596c3d1af8 | ||
|
|
4c878c27a9 | ||
|
|
5b48845dfa | ||
|
|
ce553f1211 | ||
|
|
48a4e08d60 | ||
|
|
efee0dae94 | ||
|
|
0bc2642634 | ||
|
|
429b2a9705 | ||
|
|
260e2d0dc3 | ||
|
|
6a28558d43 | ||
|
|
12181e55c0 | ||
|
|
955c7a1e5b | ||
|
|
781bfa20e8 | ||
|
|
b076bec07f | ||
|
|
11a680d7d8 | ||
|
|
bfedeed2c1 | ||
|
|
7df0dd5032 | ||
|
|
6e5b94f695 | ||
|
|
c923b2e139 | ||
|
|
97c688057d | ||
|
|
ba5e643cb2 | ||
|
|
bf26d87ee9 | ||
|
|
16b62b8e65 | ||
|
|
194791a168 | ||
|
|
846a7823ad | ||
|
|
a8cd8ad8f8 | ||
|
|
b100fd526f | ||
|
|
5724c47bcf | ||
|
|
542f1b8709 | ||
|
|
932cf21776 | ||
|
|
7386408e94 | ||
|
|
49dd839131 | ||
|
|
46be588f27 | ||
|
|
606fad64ad | ||
|
|
91b371789e | ||
|
|
204871a7ab | ||
|
|
754a74ac4a | ||
|
|
03bb9138ad | ||
|
|
bf1ad44af9 | ||
|
|
5fe47ffbec | ||
|
|
7a47994498 | ||
|
|
ece61915de | ||
|
|
1f66049a1e | ||
|
|
2fd657b768 | ||
|
|
8b5f2f9474 | ||
|
|
235b9b9269 | ||
|
|
470fef94fb | ||
|
|
82ef6bf96c | ||
|
|
b839a91050 | ||
|
|
d009c90e3a | ||
|
|
3768af4f92 | ||
|
|
d44a7ff8f9 | ||
|
|
559561ca6b | ||
|
|
713a305f45 | ||
|
|
ec5a04a6c7 | ||
|
|
a067d138e9 | ||
|
|
df1595e4bc | ||
|
|
ee6d432ced | ||
|
|
cf6eb138ce | ||
|
|
2bf73ccfe5 | ||
|
|
8c2baf0704 | ||
|
|
573c60ed6b | ||
|
|
7526ff9484 | ||
|
|
3634ad2d54 | ||
|
|
ecf9727568 |
@@ -804,7 +804,9 @@ tasks {
|
||||
":kotlin-stdlib-jdk7:publish",
|
||||
":kotlin-stdlib-jdk8:publish",
|
||||
":kotlin-reflect:publish",
|
||||
":kotlin-main-kts:publish"
|
||||
":kotlin-main-kts:publish",
|
||||
":kotlin-stdlib-js:publish",
|
||||
":kotlin-test:kotlin-test-js:publish"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,16 @@ import org.gradle.api.Project
|
||||
import org.gradle.api.publish.PublicationContainer
|
||||
import org.gradle.api.publish.PublishingExtension
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.publish.maven.tasks.PublishToMavenRepository
|
||||
import org.gradle.api.tasks.bundling.Jar
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import plugins.KotlinBuildPublishingPlugin
|
||||
import plugins.configureRepository
|
||||
import java.util.*
|
||||
|
||||
internal const val PLUGIN_MARKER_SUFFIX = ".gradle.plugin"
|
||||
|
||||
@UseExperimental(ExperimentalStdlibApi::class)
|
||||
fun Project.publishPluginMarkers(withEmptyJars: Boolean = true) {
|
||||
val pluginDevelopment = extensions.getByType<PluginBundleExtension>()
|
||||
val publishingExtension = extensions.getByType<PublishingExtension>()
|
||||
@@ -25,6 +29,10 @@ fun Project.publishPluginMarkers(withEmptyJars: Boolean = true) {
|
||||
if (withEmptyJars) {
|
||||
addEmptyJarArtifacts(markerPublication)
|
||||
}
|
||||
|
||||
tasks.named<PublishToMavenRepository>(
|
||||
"publish${markerPublication.name.capitalize(Locale.ROOT)}PublicationTo${KotlinBuildPublishingPlugin.REPOSITORY_NAME}Repository"
|
||||
).configureRepository()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,11 @@ import org.gradle.api.publish.PublishingExtension
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
|
||||
import org.gradle.api.publish.maven.tasks.PublishToMavenRepository
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import org.gradle.plugins.signing.SigningExtension
|
||||
import org.gradle.plugins.signing.SigningPlugin
|
||||
import java.net.URI
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -119,25 +121,8 @@ class KotlinBuildPublishingPlugin @Inject constructor(
|
||||
dependsOn(tasks.named("publishToMavenLocal"))
|
||||
}
|
||||
|
||||
tasks.named<PublishToMavenRepository>("publish${PUBLICATION_NAME}PublicationTo${REPOSITORY_NAME}Repository") {
|
||||
dependsOn(project.rootProject.tasks.named("preparePublication"))
|
||||
doFirst {
|
||||
val preparePublication = project.rootProject.tasks.named("preparePublication").get()
|
||||
val username: String? by preparePublication.extra
|
||||
val password: String? by preparePublication.extra
|
||||
val repoUrl: String by preparePublication.extra
|
||||
|
||||
repository.apply {
|
||||
url = uri(repoUrl)
|
||||
if (url.scheme != "file" && username != null && password != null) {
|
||||
credentials {
|
||||
this.username = username
|
||||
this.password = password
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tasks.named<PublishToMavenRepository>("publish${PUBLICATION_NAME}PublicationTo${REPOSITORY_NAME}Repository")
|
||||
.configureRepository()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -152,4 +137,24 @@ class KotlinBuildPublishingPlugin @Inject constructor(
|
||||
fun humanReadableName(project: Project) =
|
||||
project.name.split("-").joinToString(separator = " ") { it.capitalize(Locale.ROOT) }
|
||||
}
|
||||
}
|
||||
|
||||
fun TaskProvider<PublishToMavenRepository>.configureRepository() = configure {
|
||||
dependsOn(project.rootProject.tasks.named("preparePublication"))
|
||||
doFirst {
|
||||
val preparePublication = project.rootProject.tasks.named("preparePublication").get()
|
||||
val username: String? by preparePublication.extra
|
||||
val password: String? by preparePublication.extra
|
||||
val repoUrl: String by preparePublication.extra
|
||||
|
||||
repository.apply {
|
||||
url = project.uri(repoUrl)
|
||||
if (url.scheme != "file" && username != null && password != null) {
|
||||
credentials {
|
||||
this.username = username
|
||||
this.password = password
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -294,7 +294,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
val kind = KotlinBaseTest.extractConfigurationKind(testFiles)
|
||||
val jdkKind = KotlinBaseTest.getTestJdkKind(testFiles)
|
||||
val keyConfiguration = CompilerConfiguration()
|
||||
CodegenTestCase.updateConfigurationByDirectivesInTestFiles(testFiles, keyConfiguration)
|
||||
KotlinBaseTest.updateConfigurationByDirectivesInTestFiles(testFiles, keyConfiguration)
|
||||
|
||||
val key = ConfigurationKey(kind, jdkKind, keyConfiguration.toString())
|
||||
val compiler = if (isJvm8Target) {
|
||||
@@ -303,7 +303,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
val filesHolder = holders.getOrPut(key) {
|
||||
FilesWriter(compiler, KotlinTestUtils.newConfiguration(kind, jdkKind, KotlinTestUtils.getAnnotationsJar()).apply {
|
||||
println("Creating new configuration by $key")
|
||||
CodegenTestCase.updateConfigurationByDirectivesInTestFiles(testFiles, this)
|
||||
KotlinBaseTest.updateConfigurationByDirectivesInTestFiles(testFiles, this)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.backend.common
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.backend.common.bridges.findInterfaceImplementation
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
@@ -24,6 +23,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.util.getExceptionMessage
|
||||
import org.jetbrains.kotlin.util.getNonPrivateTraitMembersForDelegation
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
|
||||
|
||||
@@ -55,14 +55,8 @@ object CodegenUtil {
|
||||
@JvmOverloads
|
||||
fun getNonPrivateTraitMethods(descriptor: ClassDescriptor, copy: Boolean = true): Map<FunctionDescriptor, FunctionDescriptor> {
|
||||
val result = linkedMapOf<FunctionDescriptor, FunctionDescriptor>()
|
||||
for (declaration in DescriptorUtils.getAllDescriptors(descriptor.defaultType.memberScope)) {
|
||||
if (declaration !is CallableMemberDescriptor) continue
|
||||
|
||||
val traitMember = findInterfaceImplementation(declaration)
|
||||
if (traitMember == null ||
|
||||
Visibilities.isPrivate(traitMember.visibility) ||
|
||||
traitMember.visibility == Visibilities.INVISIBLE_FAKE) continue
|
||||
|
||||
for ((declaration, traitMember) in getNonPrivateTraitMembersForDelegation(descriptor)) {
|
||||
assert(traitMember.modality !== Modality.ABSTRACT) { "Cannot delegate to abstract trait method: $declaration" }
|
||||
|
||||
// inheritedMember can be abstract here. In order for FunctionCodegen to generate the method body, we're creating a copy here
|
||||
|
||||
@@ -24,6 +24,8 @@ import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isTypeRefinementEnabled
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.util.findImplementationFromInterface
|
||||
import org.jetbrains.kotlin.util.findInterfaceImplementation
|
||||
|
||||
fun <Signature> generateBridgesForFunctionDescriptor(
|
||||
descriptor: FunctionDescriptor,
|
||||
@@ -81,60 +83,4 @@ open class DescriptorBasedFunctionHandle(val descriptor: FunctionDescriptor) : F
|
||||
override fun toString(): String {
|
||||
return descriptor.toString()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a fake override in a class, returns an overridden declaration with implementation in trait, such that a method delegating to that
|
||||
* trait implementation should be generated into the class containing the fake override; or null if the given function is not a fake
|
||||
* override of any trait implementation or such method was already generated into the superclass or is a method from Any.
|
||||
*/
|
||||
fun findInterfaceImplementation(descriptor: CallableMemberDescriptor): CallableMemberDescriptor? {
|
||||
if (descriptor.kind.isReal) return null
|
||||
if (isOrOverridesSynthesized(descriptor)) return null
|
||||
|
||||
val implementation = findImplementationFromInterface(descriptor) ?: return null
|
||||
val immediateConcreteSuper = firstSuperMethodFromKotlin(descriptor, implementation) ?: return null
|
||||
|
||||
if (!DescriptorUtils.isInterface(immediateConcreteSuper.containingDeclaration)) {
|
||||
// If this implementation is already generated into the superclass, we need not generate it again, it'll be inherited
|
||||
return null
|
||||
}
|
||||
|
||||
return immediateConcreteSuper
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a fake override, returns an overridden non-abstract function from an interface which is the actual implementation of this function
|
||||
* that should be called when the given fake override is called.
|
||||
*/
|
||||
fun findImplementationFromInterface(descriptor: CallableMemberDescriptor): CallableMemberDescriptor? {
|
||||
val overridden = OverridingUtil.getOverriddenDeclarations(descriptor)
|
||||
val filtered = OverridingUtil.filterOutOverridden(overridden)
|
||||
|
||||
val result = filtered.firstOrNull { it.modality != Modality.ABSTRACT } ?: return null
|
||||
|
||||
if (DescriptorUtils.isClassOrEnumClass(result.containingDeclaration)) return null
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a fake override and its implementation (non-abstract declaration) somewhere in supertypes,
|
||||
* returns the first immediate super function of the given fake override which overrides that implementation.
|
||||
* The returned function should be called from TImpl-bridges generated for the given fake override.
|
||||
*/
|
||||
fun firstSuperMethodFromKotlin(
|
||||
descriptor: CallableMemberDescriptor,
|
||||
implementation: CallableMemberDescriptor
|
||||
): CallableMemberDescriptor? {
|
||||
return descriptor.overriddenDescriptors.firstOrNull { overridden ->
|
||||
overridden.modality != Modality.ABSTRACT &&
|
||||
(overridden == implementation || OverridingUtil.overrides(
|
||||
overridden,
|
||||
implementation,
|
||||
overridden.module.isTypeRefinementEnabled(),
|
||||
true
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,6 +105,15 @@ public abstract class AnnotationCodegen {
|
||||
@Nullable Annotated annotated,
|
||||
@Nullable Type returnType,
|
||||
@Nullable KotlinType typeForTypeAnnotations
|
||||
) {
|
||||
genAnnotations(annotated, returnType, typeForTypeAnnotations, null);
|
||||
}
|
||||
|
||||
public void genAnnotations(
|
||||
@Nullable Annotated annotated,
|
||||
@Nullable Type returnType,
|
||||
@Nullable KotlinType typeForTypeAnnotations,
|
||||
@Nullable DeclarationDescriptorWithVisibility parameterContainer
|
||||
) {
|
||||
if (annotated == null) return;
|
||||
|
||||
@@ -139,22 +148,23 @@ public abstract class AnnotationCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent);
|
||||
generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent, parameterContainer);
|
||||
generateTypeAnnotations(annotated, typeForTypeAnnotations);
|
||||
}
|
||||
|
||||
private void generateAdditionalAnnotations(
|
||||
@NotNull Annotated annotated,
|
||||
@Nullable Type returnType,
|
||||
@NotNull Set<String> annotationDescriptorsAlreadyPresent
|
||||
@NotNull Set<String> annotationDescriptorsAlreadyPresent,
|
||||
@Nullable DeclarationDescriptorWithVisibility parameterContainer
|
||||
) {
|
||||
if (annotated instanceof CallableDescriptor) {
|
||||
generateAdditionalCallableAnnotations((CallableDescriptor) annotated, returnType, annotationDescriptorsAlreadyPresent);
|
||||
generateAdditionalCallableAnnotations((CallableDescriptor) annotated, returnType, annotationDescriptorsAlreadyPresent, parameterContainer);
|
||||
}
|
||||
else if (annotated instanceof FieldDescriptor) {
|
||||
generateAdditionalCallableAnnotations(
|
||||
((FieldDescriptor) annotated).getCorrespondingProperty(), returnType, annotationDescriptorsAlreadyPresent
|
||||
);
|
||||
((FieldDescriptor) annotated).getCorrespondingProperty(), returnType, annotationDescriptorsAlreadyPresent,
|
||||
parameterContainer);
|
||||
}
|
||||
else if (annotated instanceof ClassDescriptor) {
|
||||
generateAdditionalClassAnnotations(annotationDescriptorsAlreadyPresent, (ClassDescriptor) annotated);
|
||||
@@ -164,11 +174,15 @@ public abstract class AnnotationCodegen {
|
||||
private void generateAdditionalCallableAnnotations(
|
||||
@NotNull CallableDescriptor descriptor,
|
||||
@Nullable Type returnType,
|
||||
@NotNull Set<String> annotationDescriptorsAlreadyPresent
|
||||
@NotNull Set<String> annotationDescriptorsAlreadyPresent,
|
||||
@Nullable DeclarationDescriptorWithVisibility parameterContainer
|
||||
) {
|
||||
// No need to annotate privates, synthetic accessors and their parameters
|
||||
if (isInvisibleFromTheOutside(descriptor)) return;
|
||||
if (descriptor instanceof ValueParameterDescriptor && isInvisibleFromTheOutside(descriptor.getContainingDeclaration())) return;
|
||||
if (descriptor instanceof ParameterDescriptor &&
|
||||
isInvisibleFromTheOutside(parameterContainer != null ? parameterContainer : descriptor.getContainingDeclaration())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// No need to annotate annotation methods since they're always non-null
|
||||
if (descriptor instanceof PropertyGetterDescriptor &&
|
||||
|
||||
@@ -39,6 +39,8 @@ import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedS
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL;
|
||||
import static org.jetbrains.kotlin.util.DeclarationUtilKt.findImplementationFromInterface;
|
||||
import static org.jetbrains.kotlin.util.DeclarationUtilKt.findInterfaceImplementation;
|
||||
|
||||
public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject> {
|
||||
@NotNull
|
||||
@@ -125,7 +127,7 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
|
||||
for (DeclarationDescriptor memberDescriptor : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) {
|
||||
if (memberDescriptor instanceof CallableMemberDescriptor) {
|
||||
CallableMemberDescriptor member = (CallableMemberDescriptor) memberDescriptor;
|
||||
if (!member.getKind().isReal() && ImplKt.findInterfaceImplementation(member) == null) {
|
||||
if (!member.getKind().isReal() && findInterfaceImplementation(member) == null) {
|
||||
if (member instanceof FunctionDescriptor) {
|
||||
functionCodegen.generateBridges((FunctionDescriptor) member);
|
||||
}
|
||||
@@ -237,11 +239,14 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
|
||||
boolean isErasedInlineClass
|
||||
) {
|
||||
// Skip Java 8 default methods
|
||||
if (CodegenUtilKt.isDefinitelyNotDefaultImplsMethod(interfaceFun) ||
|
||||
JvmAnnotationUtilKt.isCallableMemberCompiledToJvmDefault(
|
||||
DescriptorUtils.unwrapFakeOverrideToAnyDeclaration(interfaceFun), state.getJvmDefaultMode()
|
||||
)
|
||||
) {
|
||||
if (CodegenUtilKt.isDefinitelyNotDefaultImplsMethod(interfaceFun)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CallableMemberDescriptor actualImplementation =
|
||||
interfaceFun.getKind().isReal() ? interfaceFun : findImplementationFromInterface(interfaceFun);
|
||||
assert actualImplementation != null : "Can't find actual implementation for " + interfaceFun;
|
||||
if (JvmAnnotationUtilKt.isCallableMemberCompiledToJvmDefault(actualImplementation, state.getJvmDefaultMode())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -492,11 +492,11 @@ public class FunctionCodegen {
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull JvmMethodSignature jvmSignature,
|
||||
@NotNull InnerClassConsumer innerClassConsumer,
|
||||
@NotNull MemberCodegen<?> memberCodegen,
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
generateParameterAnnotations(
|
||||
functionDescriptor, mv, jvmSignature, functionDescriptor.getValueParameters(), innerClassConsumer, state
|
||||
functionDescriptor, mv, jvmSignature, functionDescriptor.getValueParameters(), memberCodegen, state
|
||||
);
|
||||
}
|
||||
|
||||
@@ -505,7 +505,7 @@ public class FunctionCodegen {
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull JvmMethodSignature jvmSignature,
|
||||
@NotNull List<ValueParameterDescriptor> valueParameters,
|
||||
@NotNull InnerClassConsumer innerClassConsumer,
|
||||
@NotNull MemberCodegen<?> memberCodegen,
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
if (isAccessor(functionDescriptor)) return;
|
||||
@@ -516,6 +516,7 @@ public class FunctionCodegen {
|
||||
|
||||
Asm7UtilKt.visitAnnotableParameterCount(mv, kotlinParameterTypes.size() - syntheticParameterCount);
|
||||
|
||||
boolean isDefaultImpl = OwnerKind.DEFAULT_IMPLS == memberCodegen.context.getContextKind();
|
||||
for (int i = 0; i < kotlinParameterTypes.size(); i++) {
|
||||
JvmMethodParameterSignature parameterSignature = kotlinParameterTypes.get(i);
|
||||
JvmMethodParameterKind kind = parameterSignature.getKind();
|
||||
@@ -528,13 +529,14 @@ public class FunctionCodegen {
|
||||
? iterator.next()
|
||||
: kind == JvmMethodParameterKind.RECEIVER
|
||||
? JvmCodegenUtil.getDirectMember(functionDescriptor).getExtensionReceiverParameter()
|
||||
: null;
|
||||
: isDefaultImpl && kind == JvmMethodParameterKind.THIS ? JvmCodegenUtil.getDirectMember(functionDescriptor)
|
||||
.getDispatchReceiverParameter() : null;
|
||||
|
||||
if (annotated != null) {
|
||||
//noinspection ConstantConditions
|
||||
int parameterIndex = i - syntheticParameterCount;
|
||||
AnnotationCodegen.forParameter(parameterIndex, mv, innerClassConsumer, state)
|
||||
.genAnnotations(annotated, parameterSignature.getAsmType(), annotated.getReturnType());
|
||||
AnnotationCodegen.forParameter(parameterIndex, mv, memberCodegen, state)
|
||||
.genAnnotations(annotated, parameterSignature.getAsmType(), annotated.getReturnType(), functionDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -606,7 +608,7 @@ public class FunctionCodegen {
|
||||
true, mv,
|
||||
method.getAsmMethod(),
|
||||
method.getOwner().getInternalName(),
|
||||
true);
|
||||
true, signature.getReturnType());
|
||||
methodEnd = new Label();
|
||||
}
|
||||
else {
|
||||
@@ -710,8 +712,7 @@ public class FunctionCodegen {
|
||||
@NotNull JvmDefaultMode jvmDefaultMode
|
||||
) {
|
||||
return OwnerKind.DEFAULT_IMPLS == context.getContextKind() &&
|
||||
JvmAnnotationUtilKt
|
||||
.isCompiledToJvmDefault(DescriptorUtils.unwrapFakeOverrideToAnyDeclaration(functionDescriptor),
|
||||
JvmAnnotationUtilKt.isCompiledToJvmDefault(DescriptorUtils.unwrapFakeOverrideToAnyDeclaration(functionDescriptor),
|
||||
jvmDefaultMode) &&
|
||||
jvmDefaultMode.isCompatibility();
|
||||
}
|
||||
@@ -849,7 +850,8 @@ public class FunctionCodegen {
|
||||
@NotNull Method asmMethod,
|
||||
@NotNull String classToDelegateTo,
|
||||
int opcode,
|
||||
boolean isInterface
|
||||
boolean isInterface,
|
||||
@NotNull Type returnType
|
||||
) {
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
Type[] argTypes = asmMethod.getArgumentTypes();
|
||||
@@ -871,7 +873,8 @@ public class FunctionCodegen {
|
||||
paramIndex += argType.getSize();
|
||||
}
|
||||
iv.visitMethodInsn(opcode, classToDelegateTo, asmMethod.getName(), asmMethod.getDescriptor(), isInterface);
|
||||
iv.areturn(asmMethod.getReturnType());
|
||||
StackValue.onStack(asmMethod.getReturnType()).coerceTo(returnType, null, iv);
|
||||
iv.areturn(returnType);
|
||||
}
|
||||
|
||||
private static void generateDelegateToStaticErasedVersion(
|
||||
@@ -910,7 +913,19 @@ public class FunctionCodegen {
|
||||
@NotNull String classToDelegateTo,
|
||||
boolean isInterfaceMethodCall
|
||||
) {
|
||||
generateDelegateToMethodBody(isStatic ? 0 : 1, mv, asmMethod, classToDelegateTo, Opcodes.INVOKESTATIC, isInterfaceMethodCall);
|
||||
generateDelegateToStaticMethodBody(isStatic, mv, asmMethod, classToDelegateTo, isInterfaceMethodCall, asmMethod.getReturnType());
|
||||
}
|
||||
|
||||
|
||||
private static void generateDelegateToStaticMethodBody(
|
||||
boolean isStatic,
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull Method asmMethod,
|
||||
@NotNull String classToDelegateTo,
|
||||
boolean isInterfaceMethodCall,
|
||||
@NotNull Type returnType
|
||||
) {
|
||||
generateDelegateToMethodBody(isStatic ? 0 : 1, mv, asmMethod, classToDelegateTo, Opcodes.INVOKESTATIC, isInterfaceMethodCall, returnType);
|
||||
}
|
||||
|
||||
private static boolean needIndexForVar(JvmMethodParameterKind kind) {
|
||||
@@ -1656,7 +1671,9 @@ public class FunctionCodegen {
|
||||
|
||||
if (JvmAnnotationUtilKt.isCompiledToJvmDefault(memberDescriptor, mode)) {
|
||||
return (kind != OwnerKind.DEFAULT_IMPLS && !isSynthetic) ||
|
||||
(kind == OwnerKind.DEFAULT_IMPLS && (isSynthetic || mode.isCompatibility()));
|
||||
(kind == OwnerKind.DEFAULT_IMPLS &&
|
||||
(isSynthetic || //TODO: move synthetic method generation into interface
|
||||
(mode.isCompatibility() && !JvmAnnotationUtilKt.hasJvmDefaultNoCompatibilityAnnotation(containingDeclaration))));
|
||||
} else {
|
||||
switch (kind) {
|
||||
case DEFAULT_IMPLS: return true;
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.backend.common.bridges.findImplementationFromInterface
|
||||
import org.jetbrains.kotlin.backend.common.bridges.firstSuperMethodFromKotlin
|
||||
import org.jetbrains.kotlin.util.findImplementationFromInterface
|
||||
import org.jetbrains.kotlin.codegen.context.ClassContext
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.state.JvmMethodExceptionTypes
|
||||
@@ -29,6 +28,7 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.util.firstSuperMethodFromKotlin
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ import org.jetbrains.kotlin.load.java.descriptors.JavaForKotlinOverridePropertyD
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.isCompiledToJvmDefault
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.hasPlatformDependentAnnotation
|
||||
import org.jetbrains.kotlin.util.findImplementationFromInterface
|
||||
import org.jetbrains.kotlin.util.findInterfaceImplementation
|
||||
|
||||
class DescriptorBasedFunctionHandleForJvm(
|
||||
descriptor: FunctionDescriptor,
|
||||
|
||||
@@ -63,8 +63,8 @@ private interface ArgsConverter<T> {
|
||||
}
|
||||
|
||||
fun tryConvertSingle(parameter: KParameter, arg: NamedArgument<T>): Result
|
||||
fun tryConvertVararg(parameter: KParameter, firstArg: NamedArgument<T>, restArgsIt: Iterator<NamedArgument<T>>): Result
|
||||
fun tryConvertTail(parameter: KParameter, firstArg: NamedArgument<T>, restArgsIt: Iterator<NamedArgument<T>>): Result
|
||||
fun tryConvertVararg(parameter: KParameter, firstArg: NamedArgument<T>, restArgs: Sequence<NamedArgument<T>>): Result
|
||||
fun tryConvertTail(parameter: KParameter, firstArg: NamedArgument<T>, restArgs: Sequence<NamedArgument<T>>): Result
|
||||
}
|
||||
|
||||
private enum class ArgsTraversalState { UNNAMED, NAMED, TAIL }
|
||||
@@ -77,7 +77,7 @@ private fun <T> tryCreateCallableMapping(
|
||||
val res = mutableMapOf<KParameter, Any?>()
|
||||
var state = ArgsTraversalState.UNNAMED
|
||||
val unboundParams = callable.parameters.toMutableList()
|
||||
val argIt = args.iterator()
|
||||
val argIt = LookAheadIterator(args.iterator())
|
||||
while (argIt.hasNext()) {
|
||||
if (unboundParams.isEmpty()) return null // failed to match: no param left for the arg
|
||||
val arg = argIt.next()
|
||||
@@ -102,7 +102,11 @@ private fun <T> tryCreateCallableMapping(
|
||||
res[par] = cvtRes.v
|
||||
} else if (par.type.jvmErasure.java.isArray) {
|
||||
// try vararg
|
||||
val cvtVRes = converter.tryConvertVararg(par, arg, argIt)
|
||||
|
||||
// Collect all the arguments that do not have a name
|
||||
val unnamed = argIt.sequenceUntil { it.name != null }
|
||||
|
||||
val cvtVRes = converter.tryConvertVararg(par, arg, unnamed)
|
||||
if (cvtVRes is ArgsConverter.Result.Success) {
|
||||
res[par] = cvtVRes.v
|
||||
} else return null // failed to match: no suitable param for unnamed arg
|
||||
@@ -121,7 +125,7 @@ private fun <T> tryCreateCallableMapping(
|
||||
ArgsTraversalState.TAIL -> {
|
||||
assert(arg.name == null)
|
||||
val par = unboundParams.removeAt(unboundParams.lastIndex)
|
||||
val cvtVRes = converter.tryConvertTail(par, arg, argIt)
|
||||
val cvtVRes = converter.tryConvertTail(par, arg, argIt.asSequence())
|
||||
if (cvtVRes is ArgsConverter.Result.Success) {
|
||||
if (argIt.hasNext()) return null // failed to match: not all tail args are consumed
|
||||
res[par] = cvtVRes.v
|
||||
@@ -162,7 +166,7 @@ private class StringArgsConverter : ArgsConverter<String> {
|
||||
override fun tryConvertVararg(
|
||||
parameter: KParameter,
|
||||
firstArg: NamedArgument<String>,
|
||||
restArgsIt: Iterator<NamedArgument<String>>
|
||||
restArgs: Sequence<NamedArgument<String>>
|
||||
): ArgsConverter.Result {
|
||||
fun convertPrimitivesArray(type: KType, args: Sequence<String?>): Any? =
|
||||
when (type.classifier) {
|
||||
@@ -179,7 +183,7 @@ private class StringArgsConverter : ArgsConverter<String> {
|
||||
|
||||
val parameterType = parameter.type
|
||||
if (parameterType.jvmErasure.java.isArray) {
|
||||
val argsSequence = sequenceOf(firstArg.value) + restArgsIt.asSequence().map { it.value }
|
||||
val argsSequence = sequenceOf(firstArg.value) + restArgs.map { it.value }
|
||||
val primArrayArgCandidate = convertPrimitivesArray(parameterType, argsSequence)
|
||||
if (primArrayArgCandidate != null)
|
||||
return ArgsConverter.Result.Success(primArrayArgCandidate)
|
||||
@@ -195,9 +199,9 @@ private class StringArgsConverter : ArgsConverter<String> {
|
||||
override fun tryConvertTail(
|
||||
parameter: KParameter,
|
||||
firstArg: NamedArgument<String>,
|
||||
restArgsIt: Iterator<NamedArgument<String>>
|
||||
restArgs: Sequence<NamedArgument<String>>
|
||||
): ArgsConverter.Result =
|
||||
tryConvertVararg(parameter, firstArg, restArgsIt)
|
||||
tryConvertVararg(parameter, firstArg, restArgs)
|
||||
}
|
||||
|
||||
private class AnyArgsConverter : ArgsConverter<Any> {
|
||||
@@ -218,18 +222,33 @@ private class AnyArgsConverter : ArgsConverter<Any> {
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (value::class.isSubclassOf(parameter.type.jvmErasure)) return ArgsConverter.Result.Success(value)
|
||||
fun evaluateValue(arg: Any): Any? {
|
||||
if (arg::class.isSubclassOf(parameter.type.jvmErasure)) return arg
|
||||
return convertPrimitivesArray(parameter.type, arg)
|
||||
}
|
||||
|
||||
return convertPrimitivesArray(parameter.type, value)?.let { ArgsConverter.Result.Success(it) }
|
||||
?: ArgsConverter.Result.Failure
|
||||
evaluateValue(value)?.let { return ArgsConverter.Result.Success(it) }
|
||||
|
||||
// Handle the scenario where [arg::class] is an Array<Any>
|
||||
// but it's values could all still be valid
|
||||
val parameterKClass = parameter.type.classifier as? KClass<*>
|
||||
val arrayComponentType = parameterKClass?.java?.takeIf { it.isArray}?.componentType?.kotlin
|
||||
|
||||
if (value is Array<*> && arrayComponentType != null) {
|
||||
// TODO: Idea! Maybe we should check if the values in the array are compatible with [arrayComponentType]
|
||||
// if they aren't perhaps we should fail silently
|
||||
convertAnyArray(arrayComponentType, value.asSequence())?.let(::evaluateValue)?.let { return ArgsConverter.Result.Success(it) }
|
||||
}
|
||||
|
||||
return ArgsConverter.Result.Failure
|
||||
}
|
||||
|
||||
override fun tryConvertVararg(
|
||||
parameter: KParameter, firstArg: NamedArgument<Any>, restArgsIt: Iterator<NamedArgument<Any>>
|
||||
parameter: KParameter, firstArg: NamedArgument<Any>, restArgs: Sequence<NamedArgument<Any>>
|
||||
): ArgsConverter.Result {
|
||||
val parameterType = parameter.type
|
||||
if (parameterType.jvmErasure.java.isArray) {
|
||||
val argsSequence = sequenceOf(firstArg.value) + restArgsIt.asSequence().map { it.value }
|
||||
val argsSequence = sequenceOf(firstArg.value) + restArgs.map { it.value }
|
||||
val arrayElementType = parameterType.arguments.firstOrNull()?.type
|
||||
val arrayArgCandidate = convertAnyArray(arrayElementType?.classifier, argsSequence)
|
||||
if (arrayArgCandidate != null)
|
||||
@@ -242,7 +261,7 @@ private class AnyArgsConverter : ArgsConverter<Any> {
|
||||
override fun tryConvertTail(
|
||||
parameter: KParameter,
|
||||
firstArg: NamedArgument<Any>,
|
||||
restArgsIt: Iterator<NamedArgument<Any>>
|
||||
restArgs: Sequence<NamedArgument<Any>>
|
||||
): ArgsConverter.Result =
|
||||
tryConvertSingle(parameter, firstArg)
|
||||
}
|
||||
@@ -266,3 +285,38 @@ private fun <T> convertAnyArrayImpl(classifier: KClassifier?, args: Sequence<T?>
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/*
|
||||
An iterator that allows us to read the next value without consuming it.
|
||||
*/
|
||||
private class LookAheadIterator<T>(private val iterator: Iterator<T>) : Iterator<T> {
|
||||
private var currentLookAhead: T? = null
|
||||
|
||||
override fun hasNext(): Boolean {
|
||||
return currentLookAhead != null || iterator.hasNext()
|
||||
}
|
||||
|
||||
override fun next(): T {
|
||||
currentLookAhead?.let { value ->
|
||||
currentLookAhead = null
|
||||
return value
|
||||
}
|
||||
|
||||
return iterator.next()
|
||||
}
|
||||
|
||||
fun nextWithoutConsuming(): T {
|
||||
return currentLookAhead ?: iterator.next().also { currentLookAhead = it }
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Will return a sequence with the values of the iterator until the predicate evaluates to true.
|
||||
*/
|
||||
private fun <T> LookAheadIterator<T>.sequenceUntil(predicate: (T) -> Boolean): Sequence<T> = sequence {
|
||||
while (hasNext()) {
|
||||
if (predicate(nextWithoutConsuming()))
|
||||
break
|
||||
yield(next())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitsExtensionsResolutionFilter
|
||||
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
|
||||
@@ -135,7 +136,8 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
declarationProviderFactory: (StorageManager, Collection<KtFile>) -> DeclarationProviderFactory,
|
||||
targetEnvironment: TargetEnvironment = CompilerEnvironment,
|
||||
sourceModuleSearchScope: GlobalSearchScope = newModuleSearchScope(project, files),
|
||||
klibList: List<KotlinLibrary> = emptyList()
|
||||
klibList: List<KotlinLibrary> = emptyList(),
|
||||
implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter? = null
|
||||
): ComponentProvider {
|
||||
val jvmTarget = configuration.get(JVMConfigurationKeys.JVM_TARGET, JvmTarget.DEFAULT)
|
||||
val languageVersionSettings = configuration.languageVersionSettings
|
||||
@@ -186,7 +188,8 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
targetEnvironment, lookupTracker, expectActualTracker,
|
||||
packagePartProvider(dependencyScope), languageVersionSettings,
|
||||
useBuiltInsProvider = true,
|
||||
configureJavaClassFinder = configureJavaClassFinder
|
||||
configureJavaClassFinder = configureJavaClassFinder,
|
||||
implicitsResolutionFilter = implicitsResolutionFilter
|
||||
)
|
||||
|
||||
moduleClassResolver.compiledCodeResolver = dependenciesContainer.get()
|
||||
@@ -220,7 +223,8 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
partProvider, languageVersionSettings,
|
||||
useBuiltInsProvider = true,
|
||||
configureJavaClassFinder = configureJavaClassFinder,
|
||||
javaClassTracker = configuration[JVMConfigurationKeys.JAVA_CLASSES_TRACKER]
|
||||
javaClassTracker = configuration[JVMConfigurationKeys.JAVA_CLASSES_TRACKER],
|
||||
implicitsResolutionFilter = implicitsResolutionFilter
|
||||
).apply {
|
||||
initJvmBuiltInsForTopDownAnalysis()
|
||||
(partProvider as? IncrementalPackagePartProvider)?.deserializationConfiguration = get()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
public open class AnnotatedMethod : R|kotlin/Any| {
|
||||
public open fun f(): R|kotlin/Unit|
|
||||
@R|kotlin/Deprecated|(message = String(Deprecated in Java)) public open fun f(): R|kotlin/Unit|
|
||||
|
||||
public constructor(): R|test/AnnotatedMethod|
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ public final annotation class Anno : R|kotlin/Annotation| {
|
||||
|
||||
}
|
||||
|
||||
@R|test/Anno|(klass = <getClass>(<getClass>(R|kotlin/String|)), klasses = <implicitArrayOf>(<getClass>(R|kotlin/Int|), <getClass>(R|kotlin/String|), <getClass>(R|kotlin/Float|)), sarKlass = <getClass>(<getClass>(R|kotlin/String|)), d2arKlass = <getClass>(<getClass>(R|kotlin/DoubleArray|))) public final class Klass : R|kotlin/Any| {
|
||||
@R|test/Anno|(klass = <getClass>(<getClass>(R|kotlin/String|)), klasses = <implicitArrayOf>(<getClass>(<getClass>(R|kotlin/Int|)), <getClass>(<getClass>(R|kotlin/String|)), <getClass>(<getClass>(R|kotlin/Float|))), sarKlass = <getClass>(<getClass>(R|kotlin/String|)), d2arKlass = <getClass>(<getClass>(R|kotlin/DoubleArray|))) public final class Klass : R|kotlin/Any| {
|
||||
public constructor(): R|test/Klass|
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public final annotation class EnumAnno : R|kotlin/Annotation| {
|
||||
}
|
||||
|
||||
public final class EnumArgumentWithCustomToString : R|kotlin/Any| {
|
||||
public final fun annotated(): R|kotlin/Unit|
|
||||
@R|test/EnumAnno|(value = R|test/E.CAKE|()) @R|test/EnumArrayAnno|(value = <implicitArrayOf>(R|test/E.CAKE|(), R|test/E.CAKE|())) public final fun annotated(): R|kotlin/Unit|
|
||||
|
||||
public constructor(): R|test/EnumArgumentWithCustomToString|
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ public final annotation class Anno : R|kotlin/Annotation| {
|
||||
}
|
||||
|
||||
public abstract interface T : R|kotlin/Any| {
|
||||
public abstract fun foo(): R|kotlin/Array<kotlin/Array<kotlin/Array<test/T>>>|
|
||||
@R|test/Anno|(s = String(foo)) public abstract fun foo(): R|kotlin/Array<kotlin/Array<kotlin/Array<test/T>>>|
|
||||
|
||||
public abstract val bar: R|kotlin/Array<kotlin/Array<kotlin/BooleanArray>>|
|
||||
public get(): R|kotlin/Array<kotlin/Array<kotlin/BooleanArray>>|
|
||||
|
||||
@@ -7,6 +7,6 @@ public final annotation class Anno : R|kotlin/Annotation| {
|
||||
}
|
||||
|
||||
public final class Constructor : R|kotlin/Any| {
|
||||
public constructor(): R|test/Constructor|
|
||||
@R|test/Anno|(value = String(string)) public constructor(): R|test/Constructor|
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ public final annotation class Anno : R|kotlin/Annotation| {
|
||||
}
|
||||
|
||||
public final class Class : R|kotlin/Any| {
|
||||
public final fun foo(): R|kotlin/Unit|
|
||||
@R|test/Anno|(t = R|java/lang/annotation/ElementType.METHOD|()) public final fun foo(): R|kotlin/Unit|
|
||||
|
||||
public final var bar: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
@@ -4,7 +4,7 @@ public final annotation class Anno : R|kotlin/Annotation| {
|
||||
}
|
||||
|
||||
public final class Class : R|kotlin/Any| {
|
||||
public final fun foo(): R|kotlin/Unit|
|
||||
@R|test/Anno|() public final fun foo(): R|kotlin/Unit|
|
||||
|
||||
public constructor(): R|test/Class|
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ public sealed class Sealed : R|kotlin/Any| {
|
||||
public final val z: R|test/Z|
|
||||
public get(): R|test/Z|
|
||||
|
||||
private constructor(z: R|test/Z|): R|test/Sealed|
|
||||
@R|test/Ann|() private constructor(z: R|test/Z|): R|test/Sealed|
|
||||
|
||||
public final class Derived : R|test/Sealed| {
|
||||
public constructor(z: R|test/Z|): R|test/Sealed.Derived|
|
||||
@@ -20,11 +20,11 @@ public final class Test : R|kotlin/Any| {
|
||||
public final val z: R|test/Z|
|
||||
public get(): R|test/Z|
|
||||
|
||||
public constructor(z: R|test/Z|, a: R|kotlin/Int|): R|test/Test|
|
||||
@R|test/Ann|() public constructor(z: R|test/Z|, a: R|kotlin/Int|): R|test/Test|
|
||||
|
||||
private constructor(z: R|test/Z|, s: R|kotlin/String|): R|test/Test|
|
||||
@R|test/Ann|() private constructor(z: R|test/Z|, s: R|kotlin/String|): R|test/Test|
|
||||
|
||||
public constructor(z: R|test/Z|): R|test/Test|
|
||||
@R|test/Ann|() public constructor(z: R|test/Z|): R|test/Test|
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,6 @@ public final inline class Z : R|kotlin/Any| {
|
||||
public final val value: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
internal constructor(value: R|kotlin/Int|): R|test/Z|
|
||||
@R|kotlin/PublishedApi|() internal constructor(value: R|kotlin/Int|): R|test/Z|
|
||||
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ public final class A : R|kotlin/Any| {
|
||||
}
|
||||
|
||||
@R|test/A.Anno|() public final class B : R|kotlin/Any| {
|
||||
public final fun f(): R|kotlin/Unit|
|
||||
@R|test/A.Anno|() public final fun f(): R|kotlin/Unit|
|
||||
|
||||
public constructor(): R|test/B|
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
public final fun foo(): R|kotlin/Unit|
|
||||
@R|test/Anno|(t = R|java/lang/annotation/ElementType.METHOD|()) public final fun foo(): R|kotlin/Unit|
|
||||
|
||||
public final annotation class Anno : R|kotlin/Annotation| {
|
||||
public final val t: R|java/lang/annotation/ElementType|
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
public final fun baz(): R|kotlin/Unit|
|
||||
@R|test/Anno|(t = <implicitArrayOf>()) public final fun baz(): R|kotlin/Unit|
|
||||
|
||||
public final fun foo(): R|kotlin/Unit|
|
||||
@R|test/Anno|(t = <implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.FIELD|())) public final fun foo(): R|kotlin/Unit|
|
||||
|
||||
public final annotation class Anno : R|kotlin/Annotation| {
|
||||
public final val t: R|kotlin/Array<out java/lang/annotation/ElementType>|
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
public final fun function(): R|kotlin/Unit|
|
||||
@R|test/Anno|() public final fun function(): R|kotlin/Unit|
|
||||
|
||||
public final annotation class Anno : R|kotlin/Annotation| {
|
||||
public constructor(): R|test/Anno|
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
public final fun baz(): R|kotlin/Unit|
|
||||
@R|test/Anno|(t = <implicitArrayOf>()) public final fun baz(): R|kotlin/Unit|
|
||||
|
||||
public final fun foo(): R|kotlin/Unit|
|
||||
@R|test/Anno|(t = <implicitArrayOf>(String(live), String(long))) public final fun foo(): R|kotlin/Unit|
|
||||
|
||||
public final annotation class Anno : R|kotlin/Annotation| {
|
||||
public final val t: R|kotlin/Array<out kotlin/String>|
|
||||
|
||||
@@ -13661,6 +13661,16 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/compatibilityResolveToOuterScopeForKotlinFunctions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("conversionForDerivedGenericClass.kt")
|
||||
public void testConversionForDerivedGenericClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/conversionForDerivedGenericClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("conversionsWithNestedGenerics.kt")
|
||||
public void testConversionsWithNestedGenerics() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/conversionsWithNestedGenerics.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enhancedSamConstructor.kt")
|
||||
public void testEnhancedSamConstructor() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/enhancedSamConstructor.kt");
|
||||
@@ -13681,6 +13691,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/kt37920.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt39630.kt")
|
||||
public void testKt39630() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/kt39630.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("privateCandidatesWithWrongArguments.kt")
|
||||
public void testPrivateCandidatesWithWrongArguments() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/privateCandidatesWithWrongArguments.kt");
|
||||
|
||||
@@ -561,6 +561,52 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
|
||||
public void testTarget8() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmDefault/target8.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmDefault/allCompatibility")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class AllCompatibility extends AbstractFirOldFrontendDiagnosticsTestWithStdlib {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInAllCompatibility() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmDefault/allCompatibility"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("specialization.kt")
|
||||
public void testSpecialization() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmDefault/allCompatibility/specialization.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmDefault/jvmDefaultWithoutCompatibility")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class JvmDefaultWithoutCompatibility extends AbstractFirOldFrontendDiagnosticsTestWithStdlib {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInJvmDefaultWithoutCompatibility() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmDefault/jvmDefaultWithoutCompatibility"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("target6.kt")
|
||||
public void testTarget6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmDefault/jvmDefaultWithoutCompatibility/target6.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("target8.kt")
|
||||
public void testTarget8() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmDefault/jvmDefaultWithoutCompatibility/target8.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("target8Disabled.kt")
|
||||
public void testTarget8Disabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmDefault/jvmDefaultWithoutCompatibility/target8Disabled.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField")
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.fir.analysis
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.FirDiagnosticsCollector
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirTransformerBasedResolveProcessor
|
||||
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.compose
|
||||
|
||||
class FirCheckersResolveProcessor(
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession
|
||||
) : FirTransformerBasedResolveProcessor(session, scopeSession) {
|
||||
val diagnosticCollector = FirDiagnosticsCollector.create(session)
|
||||
|
||||
override val transformer: FirTransformer<Nothing?> = FirCheckersRunnerTransformer(diagnosticCollector)
|
||||
}
|
||||
|
||||
class FirCheckersRunnerTransformer(private val diagnosticCollector: AbstractDiagnosticCollector) : FirTransformer<Nothing?>() {
|
||||
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
|
||||
return element.compose()
|
||||
}
|
||||
|
||||
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirDeclaration> {
|
||||
diagnosticCollector.collectDiagnostics(file)
|
||||
return file.compose()
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.isIteratorNext
|
||||
import org.jetbrains.kotlin.fir.resolve.scope
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.IntegerLiteralTypeApproximationTransformer
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperator
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
@@ -780,7 +781,12 @@ class Fir2IrVisitor(
|
||||
override fun visitGetClassCall(getClassCall: FirGetClassCall, data: Any?): IrElement {
|
||||
val argument = getClassCall.argument
|
||||
val irType = getClassCall.typeRef.toIrType()
|
||||
val irClassType = argument.typeRef.toIrType()
|
||||
val irClassType =
|
||||
if (argument is FirClassReferenceExpression) {
|
||||
argument.classTypeRef.toIrType()
|
||||
} else {
|
||||
argument.typeRef.toIrType()
|
||||
}
|
||||
val irClassReferenceSymbol = when (argument) {
|
||||
is FirResolvedReifiedParameterReference -> {
|
||||
classifierStorage.getIrTypeParameterSymbol(argument.symbol, ConversionTypeContext.DEFAULT)
|
||||
@@ -794,6 +800,12 @@ class Fir2IrVisitor(
|
||||
}
|
||||
classifierStorage.getIrClassSymbol(symbol)
|
||||
}
|
||||
is FirClassReferenceExpression -> {
|
||||
val type = argument.classTypeRef.coneTypeSafe<ConeClassLikeType>()
|
||||
(type?.lookupTag?.toSymbol(session) as? FirClassSymbol<*>)?.let {
|
||||
classifierStorage.getIrClassSymbol(it)
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
return getClassCall.convertWithOffsets { startOffset, endOffset ->
|
||||
|
||||
@@ -144,9 +144,11 @@ internal class ClassMemberGenerator(
|
||||
val classId = firFunction?.symbol?.callableId?.classId
|
||||
when {
|
||||
DataClassMembersGenerator.isComponentN(irFunction) ->
|
||||
DataClassMembersGenerator(components).generateDataClassComponentBody(irFunction, classId!!)
|
||||
firFunction?.body?.let { irFunction.body = visitor.convertToIrBlockBody(it) }
|
||||
?: DataClassMembersGenerator(components).generateDataClassComponentBody(irFunction, classId!!)
|
||||
DataClassMembersGenerator.isCopy(irFunction) ->
|
||||
DataClassMembersGenerator(components).generateDataClassCopyBody(irFunction, classId!!)
|
||||
firFunction?.body?.let { irFunction.body = visitor.convertToIrBlockBody(it) }
|
||||
?: DataClassMembersGenerator(components).generateDataClassCopyBody(irFunction, classId!!)
|
||||
else ->
|
||||
irFunction.body = firFunction?.body?.let { visitor.convertToIrBlockBody(it) }
|
||||
}
|
||||
|
||||
@@ -1284,9 +1284,9 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/boxingOptimization/kt6842.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("maxMinBy.kt")
|
||||
public void testMaxMinBy() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/boxingOptimization/maxMinBy.kt");
|
||||
@TestMetadata("maxMinByOrNull.kt")
|
||||
public void testMaxMinByOrNull() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/boxingOptimization/maxMinByOrNull.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nullCheck.kt")
|
||||
@@ -10375,6 +10375,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/enum/kt2350.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt38996.kt")
|
||||
public void testKt38996() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/kt38996.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt7257.kt")
|
||||
public void testKt7257() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/kt7257.kt");
|
||||
@@ -12404,6 +12409,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("plusAssignInsideLambda.kt")
|
||||
public void testPlusAssignInsideLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/plusAssignInsideLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsafeVarianceCodegen.kt")
|
||||
public void testUnsafeVarianceCodegen() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
||||
@@ -15763,6 +15773,24 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/delegationBy/simpleProperty.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/specialization")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Specialization extends AbstractFirBlackBoxCodegenTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTestWithCustomIgnoreDirective(this::doTest, TargetBackend.JVM_IR, testDataFilePath, "// IGNORE_BACKEND_FIR: ");
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInSpecialization() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/specialization"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("basic.kt")
|
||||
public void testBasic() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/specialization/basic.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/jvm8/defaults/noDelegation")
|
||||
|
||||
@@ -11,30 +11,32 @@ import org.jetbrains.kotlin.fir.deserialization.AbstractAnnotationDeserializer
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||
import org.jetbrains.kotlin.load.kotlin.MemberSignature
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.metadata.deserialization.TypeTable
|
||||
import org.jetbrains.kotlin.metadata.deserialization.getExtensionOrNull
|
||||
import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
|
||||
class JvmBinaryAnnotationDeserializer(
|
||||
val session: FirSession
|
||||
val session: FirSession,
|
||||
kotlinBinaryClass: KotlinJvmBinaryClass,
|
||||
byteContent: ByteArray?
|
||||
) : AbstractAnnotationDeserializer(session) {
|
||||
private val storage: MutableMap<KotlinJvmBinaryClass, MemberAnnotations> = mutableMapOf()
|
||||
|
||||
// TODO: Rename this once property constants are recorded as well
|
||||
private data class MemberAnnotations(val memberAnnotations: Map<MemberSignature, MutableList<FirAnnotationCall>>)
|
||||
private val annotationInfo by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
session.loadMemberAnnotations(kotlinBinaryClass, byteContent)
|
||||
}
|
||||
|
||||
private enum class CallableKind {
|
||||
PROPERTY_GETTER,
|
||||
PROPERTY_SETTER
|
||||
PROPERTY_SETTER,
|
||||
OTHERS
|
||||
}
|
||||
|
||||
override fun loadTypeAnnotations(typeProto: ProtoBuf.Type, nameResolver: NameResolver): List<FirAnnotationCall> {
|
||||
@@ -42,36 +44,73 @@ class JvmBinaryAnnotationDeserializer(
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver) }
|
||||
}
|
||||
|
||||
override fun loadConstructorAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
constructorProto: ProtoBuf.Constructor,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable
|
||||
): List<FirAnnotationCall> {
|
||||
val signature = getCallableSignature(constructorProto, nameResolver, typeTable) ?: return emptyList()
|
||||
return findJvmBinaryClassAndLoadMemberAnnotations(containerSource, signature)
|
||||
}
|
||||
|
||||
override fun loadFunctionAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
functionProto: ProtoBuf.Function,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable
|
||||
): List<FirAnnotationCall> {
|
||||
val signature = getCallableSignature(functionProto, nameResolver, typeTable) ?: return emptyList()
|
||||
return findJvmBinaryClassAndLoadMemberAnnotations(containerSource, signature)
|
||||
}
|
||||
|
||||
override fun loadPropertyGetterAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
propertyProto: ProtoBuf.Property,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable,
|
||||
getterFlags: Int
|
||||
): List<FirAnnotationCall> {
|
||||
val signature = getCallableSignature(propertyProto, nameResolver, CallableKind.PROPERTY_GETTER) ?: return emptyList()
|
||||
val kotlinClass = containerSource?.toKotlinJvmBinaryClass() ?: return emptyList()
|
||||
return loadMemberAnnotations(kotlinClass).memberAnnotations[signature] ?: emptyList()
|
||||
val signature = getCallableSignature(propertyProto, nameResolver, typeTable, CallableKind.PROPERTY_GETTER) ?: return emptyList()
|
||||
return findJvmBinaryClassAndLoadMemberAnnotations(containerSource, signature)
|
||||
}
|
||||
|
||||
override fun loadPropertySetterAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
propertyProto: ProtoBuf.Property,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable,
|
||||
setterFlags: Int
|
||||
): List<FirAnnotationCall> {
|
||||
val signature = getCallableSignature(propertyProto, nameResolver, CallableKind.PROPERTY_SETTER) ?: return emptyList()
|
||||
val kotlinClass = containerSource?.toKotlinJvmBinaryClass() ?: return emptyList()
|
||||
return loadMemberAnnotations(kotlinClass).memberAnnotations[signature] ?: emptyList()
|
||||
val signature = getCallableSignature(propertyProto, nameResolver, typeTable, CallableKind.PROPERTY_SETTER) ?: return emptyList()
|
||||
return findJvmBinaryClassAndLoadMemberAnnotations(containerSource, signature)
|
||||
}
|
||||
|
||||
private fun getCallableSignature(
|
||||
proto: MessageLite,
|
||||
nameResolver: NameResolver,
|
||||
kind: CallableKind
|
||||
typeTable: TypeTable,
|
||||
kind: CallableKind = CallableKind.OTHERS
|
||||
): MemberSignature? {
|
||||
return when (proto) {
|
||||
// TODO: ProtoBuf.Constructor
|
||||
// TODO: ProtoBuf.Function
|
||||
is ProtoBuf.Constructor -> {
|
||||
MemberSignature.fromJvmMemberSignature(
|
||||
JvmProtoBufUtil.getJvmConstructorSignature(proto, nameResolver, typeTable) ?: return null
|
||||
)
|
||||
}
|
||||
is ProtoBuf.Function -> {
|
||||
val signature = JvmProtoBufUtil.getJvmMethodSignature(proto, nameResolver, typeTable) ?: return null
|
||||
// TODO: Investigate why annotations for accessors affect resolution, resulting in dangling type parameter.
|
||||
// regressions: Fir2IrTextTest.Declarations.test*LevelProperties
|
||||
// This is necessary because of libraries/stdlib/src/kotlin/collections/MapAccessors.kt:43 as
|
||||
// we now load that overload as low-priority and choose another one, but we don't support @Exact yet
|
||||
// that is necessary to correctly resolve the latter
|
||||
// See KT-39659
|
||||
if (signature.name.startsWith("getVarContravariant")) {
|
||||
return null
|
||||
}
|
||||
MemberSignature.fromJvmMemberSignature(signature)
|
||||
}
|
||||
is ProtoBuf.Property -> {
|
||||
val signature = proto.getExtensionOrNull(JvmProtoBuf.propertySignature) ?: return null
|
||||
when (kind) {
|
||||
@@ -80,85 +119,85 @@ class JvmBinaryAnnotationDeserializer(
|
||||
CallableKind.PROPERTY_SETTER ->
|
||||
if (signature.hasSetter()) MemberSignature.fromMethod(nameResolver, signature.setter) else null
|
||||
// TODO: PROPERTY
|
||||
else ->
|
||||
null
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun DeserializedContainerSource.toKotlinJvmBinaryClass(): KotlinJvmBinaryClass? =
|
||||
when (this) {
|
||||
is JvmPackagePartSource -> this.knownJvmBinaryClass
|
||||
is KotlinJvmBinarySourceElement -> this.binaryClass
|
||||
else -> null
|
||||
}
|
||||
|
||||
// TODO: better to be in KotlinDeserializedJvmSymbolsProvider?
|
||||
private fun loadMemberAnnotations(kotlinClass: KotlinJvmBinaryClass): MemberAnnotations {
|
||||
if (storage.containsKey(kotlinClass)) {
|
||||
return storage[kotlinClass] ?: error("$kotlinClass should have been visited and cached.")
|
||||
}
|
||||
val memberAnnotations = hashMapOf<MemberSignature, MutableList<FirAnnotationCall>>()
|
||||
|
||||
kotlinClass.visitMembers(object : KotlinJvmBinaryClass.MemberVisitor {
|
||||
override fun visitMethod(name: Name, desc: String): KotlinJvmBinaryClass.MethodAnnotationVisitor? {
|
||||
return AnnotationVisitorForMethod(MemberSignature.fromMethodNameAndDesc(name.asString(), desc))
|
||||
}
|
||||
|
||||
override fun visitField(name: Name, desc: String, initializer: Any?): KotlinJvmBinaryClass.AnnotationVisitor? {
|
||||
val signature = MemberSignature.fromFieldNameAndDesc(name.asString(), desc)
|
||||
if (initializer != null) {
|
||||
// TODO: load constant
|
||||
}
|
||||
return MemberAnnotationVisitor(signature)
|
||||
}
|
||||
|
||||
inner class AnnotationVisitorForMethod(signature: MemberSignature) : MemberAnnotationVisitor(signature),
|
||||
KotlinJvmBinaryClass.MethodAnnotationVisitor {
|
||||
|
||||
override fun visitParameterAnnotation(
|
||||
index: Int,
|
||||
classId: ClassId,
|
||||
source: SourceElement
|
||||
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||
val paramSignature = MemberSignature.fromMethodSignatureAndParameterIndex(signature, index)
|
||||
var result = memberAnnotations[paramSignature]
|
||||
if (result == null) {
|
||||
result = arrayListOf()
|
||||
memberAnnotations[paramSignature] = result
|
||||
}
|
||||
return loadAnnotationIfNotSpecial(classId, result)
|
||||
}
|
||||
}
|
||||
|
||||
open inner class MemberAnnotationVisitor(protected val signature: MemberSignature) : KotlinJvmBinaryClass.AnnotationVisitor {
|
||||
private val result = arrayListOf<FirAnnotationCall>()
|
||||
|
||||
override fun visitAnnotation(classId: ClassId, source: SourceElement): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||
return loadAnnotationIfNotSpecial(classId, result)
|
||||
}
|
||||
|
||||
override fun visitEnd() {
|
||||
if (result.isNotEmpty()) {
|
||||
memberAnnotations[signature] = result
|
||||
}
|
||||
}
|
||||
}
|
||||
}, null) // TODO: cached file content?
|
||||
|
||||
val result = MemberAnnotations(memberAnnotations)
|
||||
storage[kotlinClass] = result
|
||||
return result
|
||||
private fun findJvmBinaryClassAndLoadMemberAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
memberSignature: MemberSignature
|
||||
): List<FirAnnotationCall> {
|
||||
return annotationInfo.memberAnnotations[memberSignature] ?: emptyList()
|
||||
}
|
||||
|
||||
// TODO: Or, better to migrate annotation deserialization in KotlinDeserializedJvmSymbolsProvider to here?
|
||||
private fun loadAnnotationIfNotSpecial(
|
||||
annotationClassId: ClassId,
|
||||
result: MutableList<FirAnnotationCall>
|
||||
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? =
|
||||
(session.firSymbolProvider as? FirCompositeSymbolProvider)
|
||||
?.providers
|
||||
?.filterIsInstance<KotlinDeserializedJvmSymbolsProvider>()
|
||||
?.singleOrNull()
|
||||
?.loadAnnotationIfNotSpecial(annotationClassId, result)
|
||||
}
|
||||
|
||||
// TODO: Rename this once property constants are recorded as well
|
||||
private data class MemberAnnotations(val memberAnnotations: Map<MemberSignature, MutableList<FirAnnotationCall>>)
|
||||
|
||||
// TODO: better to be in KotlinDeserializedJvmSymbolsProvider?
|
||||
private fun FirSession.loadMemberAnnotations(kotlinBinaryClass: KotlinJvmBinaryClass, byteContent: ByteArray?): MemberAnnotations {
|
||||
val memberAnnotations = hashMapOf<MemberSignature, MutableList<FirAnnotationCall>>()
|
||||
|
||||
kotlinBinaryClass.visitMembers(object : KotlinJvmBinaryClass.MemberVisitor {
|
||||
override fun visitMethod(name: Name, desc: String): KotlinJvmBinaryClass.MethodAnnotationVisitor? {
|
||||
return AnnotationVisitorForMethod(MemberSignature.fromMethodNameAndDesc(name.asString(), desc))
|
||||
}
|
||||
|
||||
override fun visitField(name: Name, desc: String, initializer: Any?): KotlinJvmBinaryClass.AnnotationVisitor? {
|
||||
val signature = MemberSignature.fromFieldNameAndDesc(name.asString(), desc)
|
||||
if (initializer != null) {
|
||||
// TODO: load constant
|
||||
}
|
||||
return MemberAnnotationVisitor(signature)
|
||||
}
|
||||
|
||||
inner class AnnotationVisitorForMethod(signature: MemberSignature) : MemberAnnotationVisitor(signature),
|
||||
KotlinJvmBinaryClass.MethodAnnotationVisitor {
|
||||
|
||||
override fun visitParameterAnnotation(
|
||||
index: Int,
|
||||
classId: ClassId,
|
||||
source: SourceElement
|
||||
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||
val paramSignature = MemberSignature.fromMethodSignatureAndParameterIndex(signature, index)
|
||||
var result = memberAnnotations[paramSignature]
|
||||
if (result == null) {
|
||||
result = arrayListOf()
|
||||
memberAnnotations[paramSignature] = result
|
||||
}
|
||||
return loadAnnotationIfNotSpecial(classId, result)
|
||||
}
|
||||
}
|
||||
|
||||
open inner class MemberAnnotationVisitor(protected val signature: MemberSignature) : KotlinJvmBinaryClass.AnnotationVisitor {
|
||||
private val result = arrayListOf<FirAnnotationCall>()
|
||||
|
||||
override fun visitAnnotation(classId: ClassId, source: SourceElement): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||
return loadAnnotationIfNotSpecial(classId, result)
|
||||
}
|
||||
|
||||
override fun visitEnd() {
|
||||
if (result.isNotEmpty()) {
|
||||
memberAnnotations[signature] = result
|
||||
}
|
||||
}
|
||||
}
|
||||
}, byteContent)
|
||||
|
||||
return MemberAnnotations(memberAnnotations)
|
||||
}
|
||||
|
||||
// TODO: Or, better to migrate annotation deserialization in KotlinDeserializedJvmSymbolsProvider to here?
|
||||
private fun FirSession.loadAnnotationIfNotSpecial(
|
||||
annotationClassId: ClassId,
|
||||
result: MutableList<FirAnnotationCall>
|
||||
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? =
|
||||
(firSymbolProvider as? FirCompositeSymbolProvider)
|
||||
?.providers
|
||||
?.filterIsInstance<KotlinDeserializedJvmSymbolsProvider>()
|
||||
?.singleOrNull()
|
||||
?.loadAnnotationIfNotSpecial(annotationClassId, result)
|
||||
|
||||
@@ -16,25 +16,29 @@ import org.jetbrains.kotlin.fir.declarations.FirVariable
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirSimpleFunctionImpl
|
||||
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext
|
||||
import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirClassReferenceExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.buildUnaryArgumentList
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.*
|
||||
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.java.createConstant
|
||||
import org.jetbrains.kotlin.fir.java.topLevelName
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.AbstractFirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.getClassDeclaredCallableSymbols
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.constructClassType
|
||||
import org.jetbrains.kotlin.load.java.JavaClassFinder
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.kotlin.*
|
||||
@@ -105,7 +109,8 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
return packagePartProvider.findPackageParts(packageFqName.asString()).mapNotNull { partName ->
|
||||
val classId = ClassId.topLevel(JvmClassName.byInternalName(partName).fqNameForTopLevelClassMaybeWithDollars)
|
||||
if (hasNoTopLevelClassOf(classId)) return@mapNotNull null
|
||||
val kotlinJvmBinaryClass = kotlinClassFinder.findKotlinClass(classId) ?: return@mapNotNull null
|
||||
val (kotlinJvmBinaryClass, byteContent) =
|
||||
kotlinClassFinder.findKotlinClassOrContent(classId) as? KotlinClassFinder.Result.KotlinClass ?: return@mapNotNull null
|
||||
|
||||
val header = kotlinJvmBinaryClass.classHeader
|
||||
val data = header.data ?: header.incompatibleData ?: return@mapNotNull null
|
||||
@@ -121,7 +126,7 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
packageProto,
|
||||
FirDeserializationContext.createForPackage(
|
||||
packageFqName, packageProto, nameResolver, session,
|
||||
JvmBinaryAnnotationDeserializer(session),
|
||||
JvmBinaryAnnotationDeserializer(session, kotlinJvmBinaryClass, byteContent),
|
||||
source
|
||||
),
|
||||
source,
|
||||
@@ -164,20 +169,15 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
return JvmProtoBufUtil.readClassDataFrom(data, strings)
|
||||
}
|
||||
|
||||
private fun FirClassifierSymbol<*>?.toDefaultResolvedTypeRef(classId: ClassId): FirResolvedTypeRef {
|
||||
return this?.let {
|
||||
buildResolvedTypeRef {
|
||||
type = it.constructType(emptyList(), isNullable = false)
|
||||
}
|
||||
} ?: buildErrorTypeRef { diagnostic = ConeSimpleDiagnostic("Symbol not found for $classId", DiagnosticKind.Java) }
|
||||
|
||||
}
|
||||
private fun ConeClassLikeLookupTag.toDefaultResolvedTypeRef(classId: ClassId): FirResolvedTypeRef =
|
||||
buildResolvedTypeRef {
|
||||
type = constructClassType(emptyArray(), isNullable = false)
|
||||
}
|
||||
|
||||
private fun loadAnnotation(
|
||||
annotationClassId: ClassId, result: MutableList<FirAnnotationCall>,
|
||||
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||
val lookupTag = ConeClassLikeLookupTagImpl(annotationClassId)
|
||||
val symbol = lookupTag.toSymbol(session)
|
||||
|
||||
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor {
|
||||
private val argumentMap = mutableMapOf<Name, FirExpression>()
|
||||
@@ -190,9 +190,8 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
|
||||
private fun ClassLiteralValue.toFirClassReferenceExpression(): FirClassReferenceExpression {
|
||||
val literalLookupTag = ConeClassLikeLookupTagImpl(classId)
|
||||
val literalSymbol = literalLookupTag.toSymbol(this@KotlinDeserializedJvmSymbolsProvider.session)
|
||||
return buildClassReferenceExpression {
|
||||
classTypeRef = literalSymbol.toDefaultResolvedTypeRef(classId)
|
||||
classTypeRef = literalLookupTag.toDefaultResolvedTypeRef(classId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,7 +244,11 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
}
|
||||
|
||||
override fun visitClassLiteral(value: ClassLiteralValue) {
|
||||
elements.add(value.toFirClassReferenceExpression())
|
||||
elements.add(
|
||||
buildGetClassCall {
|
||||
argumentList = buildUnaryArgumentList(value.toFirClassReferenceExpression())
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitEnd() {
|
||||
@@ -271,7 +274,7 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
|
||||
override fun visitEnd() {
|
||||
result += buildAnnotationCall {
|
||||
annotationTypeRef = symbol.toDefaultResolvedTypeRef(annotationClassId)
|
||||
annotationTypeRef = lookupTag.toDefaultResolvedTypeRef(annotationClassId)
|
||||
argumentList = buildArgumentList {
|
||||
for ((name, expression) in argumentMap) {
|
||||
arguments += buildNamedArgumentExpression {
|
||||
@@ -311,8 +314,8 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
} catch (e: ProcessCanceledException) {
|
||||
return null
|
||||
}
|
||||
val kotlinJvmBinaryClass = when (result) {
|
||||
is KotlinClassFinder.Result.KotlinClass -> result.kotlinJvmBinaryClass
|
||||
val kotlinClassWithContent = when (result) {
|
||||
is KotlinClassFinder.Result.KotlinClass -> result
|
||||
is KotlinClassFinder.Result.ClassFileContent -> {
|
||||
handledByJava.add(classId)
|
||||
return try {
|
||||
@@ -323,17 +326,19 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
}
|
||||
null -> null
|
||||
}
|
||||
if (kotlinJvmBinaryClass == null) {
|
||||
if (kotlinClassWithContent == null) {
|
||||
val outerClassId = classId.outerClassId ?: return null
|
||||
findAndDeserializeClass(outerClassId) ?: return null
|
||||
} else {
|
||||
val (kotlinJvmBinaryClass, byteContent) = kotlinClassWithContent
|
||||
|
||||
if (kotlinJvmBinaryClass.classHeader.kind != KotlinClassHeader.Kind.CLASS) return null
|
||||
val (nameResolver, classProto) = kotlinJvmBinaryClass.readClassDataFrom() ?: return null
|
||||
|
||||
val symbol = FirRegularClassSymbol(classId)
|
||||
deserializeClassToSymbol(
|
||||
classId, classProto, symbol, nameResolver, session,
|
||||
JvmBinaryAnnotationDeserializer(session),
|
||||
JvmBinaryAnnotationDeserializer(session, kotlinJvmBinaryClass, byteContent),
|
||||
kotlinScopeProvider,
|
||||
parentContext, KotlinJvmBinarySourceElement(kotlinJvmBinaryClass),
|
||||
this::findAndDeserializeClass
|
||||
@@ -352,7 +357,7 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
|
||||
|
||||
},
|
||||
null,
|
||||
byteContent,
|
||||
)
|
||||
(symbol.fir.annotations as MutableList<FirAnnotationCall>) += annotations
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ dependencies {
|
||||
|
||||
testCompileOnly(project(":kotlin-reflect-api"))
|
||||
testRuntime(project(":kotlin-reflect"))
|
||||
testRuntime(project(":core:descriptors.runtime"))
|
||||
testCompile(projectTests(":compiler:fir:analysis-tests"))
|
||||
testCompile(project(":compiler:fir:resolve"))
|
||||
testCompile(project(":compiler:fir:dump"))
|
||||
@@ -57,4 +58,4 @@ projectTest {
|
||||
}
|
||||
}
|
||||
|
||||
testsJar()
|
||||
testsJar()
|
||||
|
||||
@@ -15,10 +15,12 @@ import org.jetbrains.kotlin.cli.common.toBooleanLenient
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
||||
import org.jetbrains.kotlin.fir.analysis.FirCheckersResolveProcessor
|
||||
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.dump.MultiModuleHtmlFirDump
|
||||
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirProviderImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.createAllCompilerResolveProcessors
|
||||
@@ -38,6 +40,7 @@ private val DUMP_FIR = System.getProperty("fir.bench.dump", "true").toBooleanLen
|
||||
internal val PASSES = System.getProperty("fir.bench.passes")?.toInt() ?: 3
|
||||
internal val SEPARATE_PASS_DUMP = System.getProperty("fir.bench.dump.separate_pass", "false").toBooleanLenient()!!
|
||||
private val APPEND_ERROR_REPORTS = System.getProperty("fir.bench.report.errors.append", "false").toBooleanLenient()!!
|
||||
private val RUN_CHECKERS = System.getProperty("fir.bench.run.checkers", "false").toBooleanLenient()!!
|
||||
|
||||
class FirResolveModularizedTotalKotlinTest : AbstractModularizedTest() {
|
||||
|
||||
@@ -55,7 +58,14 @@ class FirResolveModularizedTotalKotlinTest : AbstractModularizedTest() {
|
||||
.uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(project))
|
||||
val librariesScope = ProjectScope.getLibrariesScope(project)
|
||||
val session = createSession(environment, scope, librariesScope, moduleData.qualifiedName)
|
||||
val processors = createAllCompilerResolveProcessors(session)
|
||||
val scopeSession = ScopeSession()
|
||||
val processors = createAllCompilerResolveProcessors(session, scopeSession).let {
|
||||
if (RUN_CHECKERS) {
|
||||
it + FirCheckersResolveProcessor(session, scopeSession)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
|
||||
val firProvider = session.firProvider as FirProviderImpl
|
||||
val firFiles = if (useLightTree) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf.Annotation.Argument.Value.Type.*
|
||||
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.metadata.deserialization.TypeTable
|
||||
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
@@ -45,7 +46,12 @@ abstract class AbstractAnnotationDeserializer(
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver) }
|
||||
}
|
||||
|
||||
fun loadFunctionAnnotations(functionProto: ProtoBuf.Function, nameResolver: NameResolver): List<FirAnnotationCall> {
|
||||
open fun loadFunctionAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
functionProto: ProtoBuf.Function,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable
|
||||
): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(functionProto.flags)) return emptyList()
|
||||
val annotations = functionProto.getExtension(protocol.functionAnnotation).orEmpty()
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver) }
|
||||
@@ -61,6 +67,7 @@ abstract class AbstractAnnotationDeserializer(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
propertyProto: ProtoBuf.Property,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable,
|
||||
getterFlags: Int
|
||||
): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(getterFlags)) return emptyList()
|
||||
@@ -72,6 +79,7 @@ abstract class AbstractAnnotationDeserializer(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
propertyProto: ProtoBuf.Property,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable,
|
||||
setterFlags: Int
|
||||
): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(setterFlags)) return emptyList()
|
||||
@@ -79,7 +87,12 @@ abstract class AbstractAnnotationDeserializer(
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver) }
|
||||
}
|
||||
|
||||
fun loadConstructorAnnotations(constructorProto: ProtoBuf.Constructor, nameResolver: NameResolver): List<FirAnnotationCall> {
|
||||
open fun loadConstructorAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
constructorProto: ProtoBuf.Constructor,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable
|
||||
): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(constructorProto.flags)) return emptyList()
|
||||
val annotations = constructorProto.getExtension(protocol.constructorAnnotation).orEmpty()
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver) }
|
||||
|
||||
@@ -196,7 +196,9 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
isGetter = true
|
||||
status = FirDeclarationStatusImpl(visibility, modality)
|
||||
annotations +=
|
||||
c.annotationDeserializer.loadPropertyGetterAnnotations(c.containerSource, proto, local.nameResolver, getterFlags)
|
||||
c.annotationDeserializer.loadPropertyGetterAnnotations(
|
||||
c.containerSource, proto, local.nameResolver, local.typeTable, getterFlags
|
||||
)
|
||||
this.symbol = FirPropertyAccessorSymbol()
|
||||
}
|
||||
} else {
|
||||
@@ -218,7 +220,9 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
isGetter = false
|
||||
status = FirDeclarationStatusImpl(visibility, modality)
|
||||
annotations +=
|
||||
c.annotationDeserializer.loadPropertySetterAnnotations(c.containerSource, proto, local.nameResolver, setterFlags)
|
||||
c.annotationDeserializer.loadPropertySetterAnnotations(
|
||||
c.containerSource, proto, local.nameResolver, local.typeTable, setterFlags
|
||||
)
|
||||
this.symbol = FirPropertyAccessorSymbol()
|
||||
valueParameters += proto.setterValueParameter.let {
|
||||
val parameterFlags = if (it.hasFlags()) it.flags else 0
|
||||
@@ -276,7 +280,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
}
|
||||
}
|
||||
|
||||
fun loadFunction(proto: ProtoBuf.Function): FirSimpleFunction {
|
||||
fun loadFunction(proto: ProtoBuf.Function, byteContent: ByteArray? = null): FirSimpleFunction {
|
||||
val flags = if (proto.hasFlags()) proto.flags else loadOldFlags(proto.oldFlags)
|
||||
|
||||
val receiverAnnotations =
|
||||
@@ -316,7 +320,8 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir }
|
||||
valueParameters += local.memberDeserializer.valueParameters(proto.valueParameterList)
|
||||
annotations += local.annotationDeserializer.loadFunctionAnnotations(proto, local.nameResolver)
|
||||
annotations +=
|
||||
c.annotationDeserializer.loadFunctionAnnotations(c.containerSource, proto, local.nameResolver, local.typeTable)
|
||||
this.containerSource = c.containerSource
|
||||
}
|
||||
if (proto.hasContract()) {
|
||||
@@ -366,7 +371,8 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
valueParameters += local.memberDeserializer.valueParameters(
|
||||
proto.valueParameterList, addDefaultValue = classBuilder.symbol.classId == StandardClassIds.Enum
|
||||
)
|
||||
annotations += local.annotationDeserializer.loadConstructorAnnotations(proto, local.nameResolver)
|
||||
annotations +=
|
||||
c.annotationDeserializer.loadConstructorAnnotations(c.containerSource, proto, local.nameResolver, local.typeTable)
|
||||
}.build()
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
||||
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitsExtensionsResolutionFilter
|
||||
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmDiagnosticComponents
|
||||
import org.jetbrains.kotlin.resolve.jvm.multiplatform.OptionalAnnotationPackageFragmentProvider
|
||||
@@ -63,7 +64,8 @@ fun createContainerForLazyResolveWithJava(
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
useBuiltInsProvider: Boolean,
|
||||
configureJavaClassFinder: (StorageComponentContainer.() -> Unit)? = null,
|
||||
javaClassTracker: JavaClassesTracker? = null
|
||||
javaClassTracker: JavaClassesTracker? = null,
|
||||
implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter? = null,
|
||||
): StorageComponentContainer = createContainer("LazyResolveWithJava", JvmPlatformAnalyzerServices) {
|
||||
configureModule(moduleContext, jvmPlatform, JvmPlatformAnalyzerServices, bindingTrace, languageVersionSettings)
|
||||
|
||||
@@ -73,6 +75,7 @@ fun createContainerForLazyResolveWithJava(
|
||||
useInstance(moduleContentScope)
|
||||
useInstance(packagePartProvider)
|
||||
useInstance(declarationProviderFactory)
|
||||
useInstanceIfNotNull(implicitsResolutionFilter)
|
||||
|
||||
useInstance(VirtualFileFinderFactory.getInstance(moduleContext.project).create(moduleContentScope))
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ class VirtualFileKotlinClass private constructor(
|
||||
VirtualFileKotlinClass(file, name, classVersion, header, innerClasses)
|
||||
}
|
||||
|
||||
return@time kotlinJvmBinaryClass?.let(::KotlinClass)
|
||||
return@time kotlinJvmBinaryClass?.let { KotlinClass(it, byteContent) }
|
||||
?: KotlinClassFinder.Result.ClassFileContent(byteContent)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.resolve.jvm.annotations
|
||||
|
||||
import org.jetbrains.kotlin.config.JvmDefaultMode
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
||||
@@ -19,6 +20,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||
|
||||
val JVM_DEFAULT_FQ_NAME = FqName("kotlin.jvm.JvmDefault")
|
||||
val JVM_DEFAULT_NO_COMPATIBILITY_FQ_NAME = FqName("kotlin.jvm.JvmDefaultWithoutCompatibility")
|
||||
val JVM_OVERLOADS_FQ_NAME = FqName("kotlin.jvm.JvmOverloads")
|
||||
val JVM_SYNTHETIC_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmSynthetic")
|
||||
|
||||
@@ -64,6 +66,10 @@ fun CallableMemberDescriptor.isCompiledToJvmDefault(jvmDefault: JvmDefaultMode):
|
||||
fun CallableMemberDescriptor.hasJvmDefaultAnnotation(): Boolean =
|
||||
DescriptorUtils.getDirectMember(this).annotations.hasAnnotation(JVM_DEFAULT_FQ_NAME)
|
||||
|
||||
fun DeclarationDescriptor.hasJvmDefaultNoCompatibilityAnnotation(): Boolean =
|
||||
this.annotations.hasAnnotation(JVM_DEFAULT_NO_COMPATIBILITY_FQ_NAME)
|
||||
|
||||
|
||||
fun CallableMemberDescriptor.hasPlatformDependentAnnotation(): Boolean =
|
||||
DescriptorUtils.getDirectMember(this).annotations.hasAnnotation(PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME)
|
||||
|
||||
|
||||
@@ -10,16 +10,17 @@ import org.jetbrains.kotlin.config.JvmDefaultMode
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.load.kotlin.computeJvmDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.*
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_DEFAULT_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.isCompiledToJvmDefault
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPrivateApi
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.util.getNonPrivateTraitMembersForDelegation
|
||||
|
||||
class JvmDefaultChecker(val jvmTarget: JvmTarget) : DeclarationChecker {
|
||||
|
||||
@@ -28,12 +29,22 @@ class JvmDefaultChecker(val jvmTarget: JvmTarget) : DeclarationChecker {
|
||||
|
||||
descriptor.annotations.findAnnotation(JVM_DEFAULT_FQ_NAME)?.let { annotationDescriptor ->
|
||||
val reportOn = DescriptorToSourceUtils.getSourceFromAnnotation(annotationDescriptor) ?: declaration
|
||||
if (!DescriptorUtils.isInterface(descriptor.containingDeclaration)) {
|
||||
if (!isInterface(descriptor.containingDeclaration)) {
|
||||
context.trace.report(ErrorsJvm.JVM_DEFAULT_NOT_IN_INTERFACE.on(reportOn))
|
||||
} else if (jvmTarget == JvmTarget.JVM_1_6) {
|
||||
context.trace.report(ErrorsJvm.JVM_DEFAULT_IN_JVM6_TARGET.on(reportOn))
|
||||
context.trace.report(ErrorsJvm.JVM_DEFAULT_IN_JVM6_TARGET.on(reportOn, "JvmDefault"))
|
||||
} else if (!jvmDefaultMode.isEnabled) {
|
||||
context.trace.report(ErrorsJvm.JVM_DEFAULT_IN_DECLARATION.on(declaration))
|
||||
context.trace.report(ErrorsJvm.JVM_DEFAULT_IN_DECLARATION.on(declaration, "JvmDefault"))
|
||||
}
|
||||
return@check
|
||||
}
|
||||
|
||||
descriptor.annotations.findAnnotation(JVM_DEFAULT_NO_COMPATIBILITY_FQ_NAME)?.let { annotationDescriptor ->
|
||||
val reportOn = DescriptorToSourceUtils.getSourceFromAnnotation(annotationDescriptor) ?: declaration
|
||||
if (jvmTarget == JvmTarget.JVM_1_6) {
|
||||
context.trace.report(ErrorsJvm.JVM_DEFAULT_IN_JVM6_TARGET.on(reportOn, "JvmDefaultWithoutCompatibility"))
|
||||
} else if (!jvmDefaultMode.isEnabled) {
|
||||
context.trace.report(ErrorsJvm.JVM_DEFAULT_IN_DECLARATION.on(reportOn, "JvmDefaultWithoutCompatibility"))
|
||||
}
|
||||
return@check
|
||||
}
|
||||
@@ -49,23 +60,78 @@ class JvmDefaultChecker(val jvmTarget: JvmTarget) : DeclarationChecker {
|
||||
}
|
||||
|
||||
|
||||
if (!DescriptorUtils.isInterface(descriptor.containingDeclaration)) return
|
||||
val memberDescriptor = descriptor as? CallableMemberDescriptor ?: return
|
||||
if (descriptor is PropertyAccessorDescriptor) return
|
||||
if (isInterface(descriptor.containingDeclaration)) {
|
||||
val memberDescriptor = descriptor as? CallableMemberDescriptor ?: return
|
||||
if (descriptor is PropertyAccessorDescriptor) return
|
||||
|
||||
if (memberDescriptor.overriddenDescriptors.any { it.annotations.hasAnnotation(JVM_DEFAULT_FQ_NAME) }) {
|
||||
context.trace.report(ErrorsJvm.JVM_DEFAULT_REQUIRED_FOR_OVERRIDE.on(declaration))
|
||||
} else if (jvmDefaultMode.isEnabled) {
|
||||
descriptor.overriddenDescriptors.flatMap { OverridingUtil.getOverriddenDeclarations(it) }.toSet().let {
|
||||
for (realDescriptor in OverridingUtil.filterOutOverridden(it)) {
|
||||
if (realDescriptor is JavaMethodDescriptor && realDescriptor.modality != Modality.ABSTRACT) {
|
||||
return context.trace.report(ErrorsJvm.NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT.on(declaration))
|
||||
if (memberDescriptor.overriddenDescriptors.any { it.annotations.hasAnnotation(JVM_DEFAULT_FQ_NAME) }) {
|
||||
context.trace.report(ErrorsJvm.JVM_DEFAULT_REQUIRED_FOR_OVERRIDE.on(declaration))
|
||||
} else if (jvmDefaultMode.isEnabled) {
|
||||
descriptor.overriddenDescriptors.flatMap { OverridingUtil.getOverriddenDeclarations(it) }.toSet().let {
|
||||
for (realDescriptor in OverridingUtil.filterOutOverridden(it)) {
|
||||
if (realDescriptor is JavaMethodDescriptor && realDescriptor.modality != Modality.ABSTRACT) {
|
||||
return context.trace.report(ErrorsJvm.NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT.on(declaration))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (jvmDefaultMode.isCompatibility &&
|
||||
!isInterface(descriptor) &&
|
||||
!isAnnotationClass(descriptor) &&
|
||||
descriptor is ClassDescriptor &&
|
||||
!descriptor.hasJvmDefaultNoCompatibilityAnnotation()
|
||||
) {
|
||||
val modality = descriptor.modality
|
||||
//TODO: maybe remove this check for jvm compatibility
|
||||
if (modality !== Modality.OPEN && modality !== Modality.ABSTRACT || descriptor.isEffectivelyPrivateApi) return
|
||||
for ((inheritedMember, actualImplementation) in getNonPrivateTraitMembersForDelegation(
|
||||
descriptor,
|
||||
returnImplNotDelegate = true
|
||||
)) {
|
||||
if (actualImplementation.isCallableMemberCompiledToJvmDefault(jvmDefaultMode)) {
|
||||
if (actualImplementation is FunctionDescriptor && inheritedMember is FunctionDescriptor) {
|
||||
processMember(inheritedMember, actualImplementation, context, declaration)
|
||||
} else if (actualImplementation is PropertyDescriptor && inheritedMember is PropertyDescriptor) {
|
||||
val getterImpl = actualImplementation.getter
|
||||
val getterInherited = inheritedMember.getter
|
||||
if (getterImpl == null || getterInherited == null || processMember(getterImpl, getterImpl, context, declaration)) {
|
||||
if (actualImplementation.isVar && inheritedMember.isVar) {
|
||||
val setterImpl = actualImplementation.setter
|
||||
val setterInherited = inheritedMember.setter
|
||||
if (setterImpl != null && setterInherited != null) {
|
||||
processMember(setterImpl, setterImpl, context, declaration)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun processMember(
|
||||
inheritedFun: FunctionDescriptor,
|
||||
actualImplementation: FunctionDescriptor,
|
||||
context: DeclarationCheckerContext,
|
||||
declaration: KtDeclaration
|
||||
): Boolean {
|
||||
val inheritedSignature = inheritedFun.computeJvmDescriptor(withReturnType = true, withName = false)
|
||||
val originalImplementation = actualImplementation.original
|
||||
val actualSignature = originalImplementation.computeJvmDescriptor(withReturnType = true, withName = false)
|
||||
if (inheritedSignature != actualSignature) {
|
||||
//NB: this diagnostics should be a bit tuned, see box/jvm8/defaults/allCompatibility/kt14243_2.kt for details
|
||||
context.trace.report(
|
||||
ErrorsJvm.EXPLICIT_OVERRIDE_REQUIRED_IN_COMPATIBILITY_MODE.on(
|
||||
declaration,
|
||||
getDirectMember(inheritedFun),
|
||||
getDirectMember(originalImplementation)
|
||||
)
|
||||
)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun checkJvmDefaultsInHierarchy(descriptor: DeclarationDescriptor, jvmDefaultMode: JvmDefaultMode): Boolean {
|
||||
if (jvmDefaultMode.isEnabled) return true
|
||||
|
||||
|
||||
@@ -135,9 +135,9 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
"See https://youtrack.jetbrains.com/issue/KT-21354 for more details");
|
||||
|
||||
MAP.put(JVM_DEFAULT_NOT_IN_INTERFACE,"'@JvmDefault' is only supported on interface members");
|
||||
MAP.put(JVM_DEFAULT_IN_JVM6_TARGET,"'@JvmDefault' is only supported since JVM target 1.8. Recompile with '-jvm-target 1.8'");
|
||||
MAP.put(JVM_DEFAULT_IN_JVM6_TARGET,"''@{0}'' is only supported since JVM target 1.8. Recompile with ''-jvm-target 1.8''", STRING);
|
||||
MAP.put(JVM_DEFAULT_REQUIRED_FOR_OVERRIDE, "'@JvmDefault' is required for an override of a '@JvmDefault' member");
|
||||
MAP.put(JVM_DEFAULT_IN_DECLARATION, "Usage of '@JvmDefault' is only allowed with -Xjvm-default option");
|
||||
MAP.put(JVM_DEFAULT_IN_DECLARATION, "Usage of ''@{0}'' is only allowed with -Xjvm-default option", STRING);
|
||||
MAP.put(JVM_DEFAULT_THROUGH_INHERITANCE, "Inheritance from an interface with '@JvmDefault' members is only allowed with -Xjvm-default option");
|
||||
MAP.put(USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL, "Super calls of '@JvmDefault' members are only allowed with -Xjvm-default option");
|
||||
MAP.put(NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT, "Non-@JvmDefault interface method cannot override default Java method. Please annotate this method with @JvmDefault");
|
||||
@@ -159,6 +159,12 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
|
||||
MAP.put(FUNCTION_DELEGATE_MEMBER_NAME_CLASH,
|
||||
"Functional interface member cannot have this name on JVM because it clashes with an internal member getFunctionDelegate");
|
||||
|
||||
MAP.put(EXPLICIT_OVERRIDE_REQUIRED_IN_COMPATIBILITY_MODE,
|
||||
"Compatibility mode requires to explicitly override ''{1}'' with specialization ''{0}'', " +
|
||||
"or annotate the class with @JvmDefaultWithoutCompatibility. " +
|
||||
"Please refer to KT-39603 for details",
|
||||
COMPACT, SHORT_NAMES_IN_TYPES);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -108,9 +108,9 @@ public interface ErrorsJvm {
|
||||
DiagnosticFactory0<KtExpression> ASSIGNMENT_TO_ARRAY_LOOP_VARIABLE = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
DiagnosticFactory0<PsiElement> JVM_DEFAULT_NOT_IN_INTERFACE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> JVM_DEFAULT_IN_JVM6_TARGET = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> JVM_DEFAULT_IN_JVM6_TARGET = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<KtDeclaration> JVM_DEFAULT_REQUIRED_FOR_OVERRIDE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<KtDeclaration> JVM_DEFAULT_IN_DECLARATION = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory1<KtElement, String> JVM_DEFAULT_IN_DECLARATION = DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
DiagnosticFactory0<KtDeclaration> JVM_DEFAULT_THROUGH_INHERITANCE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<PsiElement> USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
@@ -139,6 +139,8 @@ public interface ErrorsJvm {
|
||||
|
||||
DiagnosticFactory0<PsiElement> FUNCTION_DELEGATE_MEMBER_NAME_CLASH = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory2<KtDeclaration, CallableDescriptor, CallableDescriptor> EXPLICIT_OVERRIDE_REQUIRED_IN_COMPATIBILITY_MODE = DiagnosticFactory2.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
Object _initializer = new Object() {
|
||||
{
|
||||
|
||||
@@ -74,6 +74,7 @@ class NewResolutionOldInference(
|
||||
private val coroutineInferenceSupport: CoroutineInferenceSupport,
|
||||
private val deprecationResolver: DeprecationResolver,
|
||||
private val typeApproximator: TypeApproximator,
|
||||
private val implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter,
|
||||
private val callResolver: CallResolver,
|
||||
private val candidateInterceptor: CandidateInterceptor
|
||||
) {
|
||||
@@ -174,7 +175,7 @@ class NewResolutionOldInference(
|
||||
|
||||
val dynamicScope = dynamicCallableDescriptors.createDynamicDescriptorScope(context.call, context.scope.ownerDescriptor)
|
||||
val scopeTower = ImplicitScopeTowerImpl(
|
||||
context, dynamicScope, syntheticScopes, context.call.createLookupLocation(), typeApproximator, callResolver, candidateInterceptor
|
||||
context, dynamicScope, syntheticScopes, context.call.createLookupLocation(), typeApproximator, implicitsResolutionFilter, callResolver, candidateInterceptor
|
||||
)
|
||||
|
||||
val shouldUseOperatorRem = languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)
|
||||
@@ -362,6 +363,7 @@ class NewResolutionOldInference(
|
||||
override val syntheticScopes: SyntheticScopes,
|
||||
override val location: LookupLocation,
|
||||
override val typeApproximator: TypeApproximator,
|
||||
override val implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter,
|
||||
val callResolver: CallResolver,
|
||||
val candidateInterceptor: CandidateInterceptor
|
||||
) : ImplicitScopeTower {
|
||||
|
||||
@@ -61,6 +61,7 @@ class PSICallResolver(
|
||||
private val kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer,
|
||||
private val kotlinCallResolver: KotlinCallResolver,
|
||||
private val typeApproximator: TypeApproximator,
|
||||
private val implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter,
|
||||
private val argumentTypeResolver: ArgumentTypeResolver,
|
||||
private val effectSystem: EffectSystem,
|
||||
private val constantExpressionEvaluator: ConstantExpressionEvaluator,
|
||||
@@ -393,6 +394,7 @@ class PSICallResolver(
|
||||
override val isNewInferenceEnabled: Boolean get() = context.languageVersionSettings.supportsFeature(LanguageFeature.NewInference)
|
||||
override val lexicalScope: LexicalScope get() = context.scope
|
||||
override val typeApproximator: TypeApproximator get() = this@PSICallResolver.typeApproximator
|
||||
override val implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter get() = this@PSICallResolver.implicitsResolutionFilter
|
||||
private val cache = HashMap<ReceiverParameterDescriptor, ReceiverValueWithSmartCastInfo>()
|
||||
|
||||
override fun getImplicitReceiver(scope: LexicalScope): ReceiverValueWithSmartCastInfo? {
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProv
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.PackageMemberDeclarationProvider
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.flatMapToNullable
|
||||
import java.util.*
|
||||
|
||||
//----------------------------------------------------------------
|
||||
@@ -43,6 +44,13 @@ interface SyntheticResolveExtension {
|
||||
override fun getSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List<Name> =
|
||||
instances.flatMap { withLinkageErrorLogger(it) { getSyntheticNestedClassNames(thisDescriptor) } }
|
||||
|
||||
override fun getPossibleSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List<Name>? =
|
||||
instances.flatMapToNullable(ArrayList<Name>()) {
|
||||
withLinkageErrorLogger(it) {
|
||||
getPossibleSyntheticNestedClassNames(thisDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSyntheticFunctionNames(thisDescriptor: ClassDescriptor): List<Name> =
|
||||
instances.flatMap { withLinkageErrorLogger(it) { getSyntheticFunctionNames(thisDescriptor) } }
|
||||
|
||||
@@ -136,6 +144,13 @@ interface SyntheticResolveExtension {
|
||||
|
||||
fun getSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List<Name> = emptyList()
|
||||
|
||||
/**
|
||||
* This method should return either superset of what [getSyntheticNestedClassNames] returns,
|
||||
* or null in case it needs to run resolution and inference and/or it is very costly.
|
||||
* Override this method if resolution started to fail with recursion.
|
||||
*/
|
||||
fun getPossibleSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List<Name>? = getSyntheticNestedClassNames(thisDescriptor)
|
||||
|
||||
fun addSyntheticSupertypes(thisDescriptor: ClassDescriptor, supertypes: MutableList<KotlinType>) {}
|
||||
|
||||
fun generateSyntheticClasses(
|
||||
|
||||
@@ -58,11 +58,11 @@ class FileScopeFactory(
|
||||
override val importedFqName: FqName? get() = importPath.fqName
|
||||
}
|
||||
|
||||
fun createScopesForFile(file: KtFile, existingImports: ImportingScope? = null): FileScopes {
|
||||
fun createScopesForFile(file: KtFile, existingImports: ImportingScope? = null, createDefaultImportingScopes: Boolean = true): FileScopes {
|
||||
val packageView = components.moduleDescriptor.getPackage(file.packageFqName)
|
||||
val packageFragment = topLevelDescriptorProvider.getPackageFragmentOrDiagnoseFailure(file.packageFqName, file)
|
||||
|
||||
return FilesScopesBuilder(file, existingImports, packageFragment, packageView).result
|
||||
return FilesScopesBuilder(file, existingImports, packageFragment, packageView, createDefaultImportingScopes).result
|
||||
}
|
||||
|
||||
private data class DefaultImportResolvers(
|
||||
@@ -137,7 +137,8 @@ class FileScopeFactory(
|
||||
private val file: KtFile,
|
||||
private val existingImports: ImportingScope?,
|
||||
private val packageFragment: PackageFragmentDescriptor,
|
||||
private val packageView: PackageViewDescriptor
|
||||
private val packageView: PackageViewDescriptor,
|
||||
private val createDefaultImportingScopes: Boolean,
|
||||
) {
|
||||
val imports = file.importDirectives
|
||||
val aliasImportNames = imports.mapNotNull { if (it.aliasName != null) it.importedFqName else null }
|
||||
@@ -197,15 +198,17 @@ class FileScopeFactory(
|
||||
|
||||
val dummyContainerDescriptor = DummyContainerDescriptor(file, packageFragment)
|
||||
|
||||
var scope: ImportingScope
|
||||
var scope: ImportingScope? = existingImports
|
||||
|
||||
val debugName = "LazyFileScope for file " + file.name
|
||||
|
||||
scope = LazyImportScope(
|
||||
existingImports, defaultAllUnderImportResolver, defaultLowPriorityImportResolver,
|
||||
LazyImportScope.FilteringKind.INVISIBLE_CLASSES,
|
||||
"Default all under imports in $debugName (invisible classes only)"
|
||||
)
|
||||
if (createDefaultImportingScopes) {
|
||||
scope = LazyImportScope(
|
||||
scope, defaultAllUnderImportResolver, defaultLowPriorityImportResolver,
|
||||
LazyImportScope.FilteringKind.INVISIBLE_CLASSES,
|
||||
"Default all under imports in $debugName (invisible classes only)"
|
||||
)
|
||||
}
|
||||
|
||||
scope = LazyImportScope(
|
||||
scope, allUnderImportResolver, null, LazyImportScope.FilteringKind.INVISIBLE_CLASSES,
|
||||
@@ -214,20 +217,24 @@ class FileScopeFactory(
|
||||
|
||||
scope = currentPackageScope(packageView, aliasImportNames, dummyContainerDescriptor, FilteringKind.INVISIBLE_CLASSES, scope)
|
||||
|
||||
scope = LazyImportScope(
|
||||
scope, defaultAllUnderImportResolver, defaultLowPriorityImportResolver, LazyImportScope.FilteringKind.VISIBLE_CLASSES,
|
||||
"Default all under imports in $debugName (visible classes)"
|
||||
)
|
||||
if (createDefaultImportingScopes) {
|
||||
scope = LazyImportScope(
|
||||
scope, defaultAllUnderImportResolver, defaultLowPriorityImportResolver, LazyImportScope.FilteringKind.VISIBLE_CLASSES,
|
||||
"Default all under imports in $debugName (visible classes)"
|
||||
)
|
||||
}
|
||||
|
||||
scope = LazyImportScope(
|
||||
scope, allUnderImportResolver, null, LazyImportScope.FilteringKind.VISIBLE_CLASSES,
|
||||
"All under imports in $debugName (visible classes)"
|
||||
)
|
||||
|
||||
scope = LazyImportScope(
|
||||
scope, defaultExplicitImportResolver, null, LazyImportScope.FilteringKind.ALL,
|
||||
"Default explicit imports in $debugName"
|
||||
)
|
||||
if (createDefaultImportingScopes) {
|
||||
scope = LazyImportScope(
|
||||
scope, defaultExplicitImportResolver, null, LazyImportScope.FilteringKind.ALL,
|
||||
"Default explicit imports in $debugName"
|
||||
)
|
||||
}
|
||||
|
||||
scope = SubpackagesImportingScope(scope, components.moduleDescriptor, FqName.ROOT)
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.storage.getValue
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
||||
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.flatMapToNullable
|
||||
import java.util.*
|
||||
|
||||
open class LazyClassMemberScope(
|
||||
@@ -102,7 +103,7 @@ open class LazyClassMemberScope(
|
||||
}
|
||||
|
||||
private val _variableNames: MutableSet<Name>
|
||||
by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
by storageManager.createLazyValue {
|
||||
mutableSetOf<Name>().apply {
|
||||
addAll(declarationProvider.getDeclarationNames())
|
||||
supertypes.flatMapTo(this) {
|
||||
@@ -112,9 +113,10 @@ open class LazyClassMemberScope(
|
||||
}
|
||||
|
||||
private val _functionNames: MutableSet<Name>
|
||||
by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
by storageManager.createLazyValue {
|
||||
mutableSetOf<Name>().apply {
|
||||
addAll(declarationProvider.getDeclarationNames())
|
||||
addAll(c.syntheticResolveExtension.getSyntheticFunctionNames(thisDescriptor))
|
||||
supertypes.flatMapTo(this) {
|
||||
it.memberScope.getFunctionNames()
|
||||
}
|
||||
@@ -123,6 +125,32 @@ open class LazyClassMemberScope(
|
||||
}
|
||||
}
|
||||
|
||||
private val _classifierNames: Set<Name>?
|
||||
by storageManager.createNullableLazyValue {
|
||||
mutableSetOf<Name>().apply {
|
||||
supertypes.flatMapToNullable(this) {
|
||||
it.memberScope.getClassifierNames()
|
||||
} ?: return@createNullableLazyValue null
|
||||
|
||||
addAll(declarationProvider.getDeclarationNames())
|
||||
with(c.syntheticResolveExtension) {
|
||||
getPossibleSyntheticNestedClassNames(thisDescriptor)?.let { addAll(it) } ?: return@createNullableLazyValue null
|
||||
getSyntheticCompanionObjectNameIfNeeded(thisDescriptor)?.let { add(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val _allNames: Set<Name>?
|
||||
by storageManager.createNullableLazyValue {
|
||||
val classifiers = getClassifierNames() ?: return@createNullableLazyValue null
|
||||
|
||||
mutableSetOf<Name>().apply {
|
||||
addAll(getVariableNames())
|
||||
addAll(getFunctionNames())
|
||||
addAll(classifiers)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDataClassRelatedFunctionNames(): Collection<Name> {
|
||||
val declarations = mutableListOf<DeclarationDescriptor>()
|
||||
addDataClassMethods(declarations, NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS)
|
||||
@@ -131,6 +159,11 @@ open class LazyClassMemberScope(
|
||||
|
||||
override fun getVariableNames() = _variableNames
|
||||
override fun getFunctionNames() = _functionNames
|
||||
override fun getClassifierNames() = _classifierNames
|
||||
|
||||
override fun definitelyDoesNotContainName(name: Name): Boolean {
|
||||
return _allNames?.let { name !in it } ?: false
|
||||
}
|
||||
|
||||
private interface MemberExtractor<out T : CallableMemberDescriptor> {
|
||||
fun extract(extractFrom: KotlinType, name: Name): Collection<T>
|
||||
|
||||
@@ -248,7 +248,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
// Check for '+'
|
||||
// We should clear calls info for coroutine inference within right side as here we analyze it a second time in another context
|
||||
if (context.inferenceSession instanceof CoroutineInferenceSession) {
|
||||
((CoroutineInferenceSession) context.inferenceSession).clearCallsInfoByContainingElement(expression);
|
||||
((CoroutineInferenceSession) context.inferenceSession).clearCallsInfoByContainingElement(right);
|
||||
}
|
||||
Name counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
|
||||
binaryOperationDescriptors = components.callResolver.resolveBinaryCall(
|
||||
|
||||
@@ -6,11 +6,17 @@
|
||||
package org.jetbrains.kotlin.util
|
||||
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.containingDeclarationForPseudocode
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isTypeRefinementEnabled
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
|
||||
fun KtElement.containingNonLocalDeclaration(): KtDeclaration? {
|
||||
var container = this.containingDeclarationForPseudocode
|
||||
@@ -27,3 +33,78 @@ val KtDeclaration.isOrdinaryClass
|
||||
!this.isInterface()
|
||||
|
||||
val KtDeclaration.isAnnotated get() = this.annotationEntries.isNotEmpty()
|
||||
|
||||
/**
|
||||
* Given a fake override, returns an overridden non-abstract function from an interface which is the actual implementation of this function
|
||||
* that should be called when the given fake override is called.
|
||||
*/
|
||||
fun findImplementationFromInterface(descriptor: CallableMemberDescriptor): CallableMemberDescriptor? {
|
||||
val overridden = OverridingUtil.getOverriddenDeclarations(descriptor)
|
||||
val filtered = OverridingUtil.filterOutOverridden(overridden)
|
||||
|
||||
val result = filtered.firstOrNull { it.modality != Modality.ABSTRACT } ?: return null
|
||||
|
||||
if (DescriptorUtils.isClassOrEnumClass(result.containingDeclaration)) return null
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a fake override in a class, returns an overridden declaration with implementation in trait, such that a method delegating to that
|
||||
* trait implementation should be generated into the class containing the fake override; or null if the given function is not a fake
|
||||
* override of any trait implementation or such method was already generated into the superclass or is a method from Any.
|
||||
*/
|
||||
@JvmOverloads
|
||||
fun findInterfaceImplementation(descriptor: CallableMemberDescriptor, returnImplNotDelegate: Boolean = false): CallableMemberDescriptor? {
|
||||
if (descriptor.kind.isReal) return null
|
||||
if (isOrOverridesSynthesized(descriptor)) return null
|
||||
|
||||
val implementation = findImplementationFromInterface(descriptor) ?: return null
|
||||
val immediateConcreteSuper = firstSuperMethodFromKotlin(descriptor, implementation) ?: return null
|
||||
|
||||
if (!DescriptorUtils.isInterface(immediateConcreteSuper.containingDeclaration)) {
|
||||
// If this implementation is already generated into the superclass, we need not generate it again, it'll be inherited
|
||||
return null
|
||||
}
|
||||
|
||||
return if (returnImplNotDelegate) implementation else immediateConcreteSuper
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a fake override and its implementation (non-abstract declaration) somewhere in supertypes,
|
||||
* returns the first immediate super function of the given fake override which overrides that implementation.
|
||||
* The returned function should be called from TImpl-bridges generated for the given fake override.
|
||||
*/
|
||||
fun firstSuperMethodFromKotlin(
|
||||
descriptor: CallableMemberDescriptor,
|
||||
implementation: CallableMemberDescriptor
|
||||
): CallableMemberDescriptor? {
|
||||
return descriptor.overriddenDescriptors.firstOrNull { overridden ->
|
||||
overridden.modality != Modality.ABSTRACT &&
|
||||
(overridden == implementation || OverridingUtil.overrides(
|
||||
overridden,
|
||||
implementation,
|
||||
overridden.module.isTypeRefinementEnabled(),
|
||||
true
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun getNonPrivateTraitMembersForDelegation(
|
||||
descriptor: ClassDescriptor,
|
||||
returnImplNotDelegate: Boolean = false,
|
||||
): Map<CallableMemberDescriptor, CallableMemberDescriptor> {
|
||||
val result = linkedMapOf<CallableMemberDescriptor, CallableMemberDescriptor>()
|
||||
for (declaration in DescriptorUtils.getAllDescriptors(descriptor.defaultType.memberScope)) {
|
||||
if (declaration !is CallableMemberDescriptor) continue
|
||||
|
||||
val traitMember = findInterfaceImplementation(declaration, returnImplNotDelegate)
|
||||
if (traitMember == null ||
|
||||
Visibilities.isPrivate(traitMember.visibility) ||
|
||||
traitMember.visibility == Visibilities.INVISIBLE_FAKE
|
||||
) continue
|
||||
result[declaration] = traitMember
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -158,6 +158,12 @@ open class IrBuildingTransformer(private val context: BackendContext) : IrElemen
|
||||
return super.visitAnonymousInitializer(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitEnumEntry(declaration: IrEnumEntry): IrStatement {
|
||||
withBuilder(declaration.symbol) {
|
||||
return super.visitEnumEntry(declaration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
|
||||
@@ -147,13 +147,14 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
|
||||
val inlinePrefix = if (wrapperVisibility == Visibilities.PUBLIC) "\$i" else ""
|
||||
val wrapperName = Name.identifier("sam$inlinePrefix\$$superFqName$SAM_WRAPPER_SUFFIX")
|
||||
val superMethod = superClass.functions.single { it.modality == Modality.ABSTRACT }
|
||||
val extensionReceiversCount = if (superMethod.extensionReceiverParameter == null) 0 else 1
|
||||
// TODO: have psi2ir cast the argument to the correct function type. Also see the TODO
|
||||
// about type parameters in `visitTypeOperator`.
|
||||
val wrappedFunctionClass =
|
||||
if (superMethod.isSuspend)
|
||||
context.ir.symbols.suspendFunctionN(superMethod.valueParameters.size).owner
|
||||
context.ir.symbols.suspendFunctionN(superMethod.valueParameters.size + extensionReceiversCount).owner
|
||||
else
|
||||
context.ir.symbols.functionN(superMethod.valueParameters.size).owner
|
||||
context.ir.symbols.functionN(superMethod.valueParameters.size + extensionReceiversCount).owner
|
||||
val wrappedFunctionType = wrappedFunctionClass.defaultType
|
||||
|
||||
val subclass = buildClass {
|
||||
@@ -204,11 +205,13 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
|
||||
}.apply {
|
||||
overriddenSymbols = listOf(superMethod.symbol)
|
||||
dispatchReceiverParameter = subclass.thisReceiver!!.copyTo(this)
|
||||
extensionReceiverParameter = superMethod.extensionReceiverParameter?.copyTo(this)
|
||||
valueParameters = superMethod.valueParameters.map { it.copyTo(this) }
|
||||
body = context.createIrBuilder(symbol).irBlockBody {
|
||||
+irReturn(irCall(wrappedFunctionClass.functions.single { it.name == OperatorNameConventions.INVOKE }).apply {
|
||||
dispatchReceiver = irGetField(irGet(dispatchReceiverParameter!!), field)
|
||||
valueParameters.forEachIndexed { i, parameter -> putValueArgument(i, irGet(parameter)) }
|
||||
extensionReceiverParameter?.let { putValueArgument(0, irGet(it)) }
|
||||
valueParameters.forEachIndexed { i, parameter -> putValueArgument(extensionReceiversCount + i, irGet(parameter)) }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,10 @@ import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.defaultType
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeBuilder
|
||||
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.isLong
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.findDeclaration
|
||||
@@ -300,6 +301,10 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
|
||||
val jsBoxIntrinsic = getInternalFunction("boxIntrinsic")
|
||||
val jsUnboxIntrinsic = getInternalFunction("unboxIntrinsic")
|
||||
|
||||
val createSharedBox = defineCreateSharedBox()
|
||||
val readSharedBox = defineReadSharedBox()
|
||||
val writeSharedBox = defineWriteSharedBox()
|
||||
|
||||
// Helpers:
|
||||
|
||||
private fun getInternalFunction(name: String) =
|
||||
@@ -329,6 +334,68 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
|
||||
}
|
||||
}
|
||||
|
||||
private fun defineCreateSharedBox(): IrSimpleFunction {
|
||||
return externalPackageFragment.addFunction {
|
||||
name = Name.identifier("\$sharedBox\$create")
|
||||
origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB
|
||||
returnType = context.dynamicType
|
||||
}.apply {
|
||||
val tp = addTypeParameter("T", irBuiltIns.anyNType)
|
||||
addValueParameter {
|
||||
index = 0
|
||||
name = Name.identifier("v")
|
||||
type = IrSimpleTypeBuilder().run {
|
||||
classifier = tp.symbol
|
||||
hasQuestionMark = true
|
||||
buildSimpleType()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun defineReadSharedBox(): IrSimpleFunction {
|
||||
return externalPackageFragment.addFunction {
|
||||
name = Name.identifier("\$sharedBox\$read")
|
||||
origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB
|
||||
}.apply {
|
||||
val tp = addTypeParameter("T", irBuiltIns.anyNType)
|
||||
returnType = IrSimpleTypeBuilder().run {
|
||||
classifier = tp.symbol
|
||||
hasQuestionMark = true
|
||||
buildSimpleType()
|
||||
}
|
||||
addValueParameter {
|
||||
index = 0
|
||||
name = Name.identifier("box")
|
||||
type = context.dynamicType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun defineWriteSharedBox(): IrSimpleFunction {
|
||||
return externalPackageFragment.addFunction {
|
||||
name = Name.identifier("\$sharedBox\$write")
|
||||
origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB
|
||||
returnType = irBuiltIns.unitType
|
||||
}.apply {
|
||||
val tp = addTypeParameter("T", irBuiltIns.anyNType)
|
||||
addValueParameter {
|
||||
index = 0
|
||||
name = Name.identifier("box")
|
||||
type = context.dynamicType
|
||||
}
|
||||
addValueParameter {
|
||||
index = 1
|
||||
name = Name.identifier("nv")
|
||||
type = IrSimpleTypeBuilder().run {
|
||||
classifier = tp.symbol
|
||||
hasQuestionMark = true
|
||||
buildSimpleType()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun defineEs6DefaultTypeIntrinsic(): IrSimpleFunction {
|
||||
return externalPackageFragment.addFunction {
|
||||
name = Name.identifier("DefaultType")
|
||||
|
||||
@@ -91,7 +91,7 @@ class JsIrBackendContext(
|
||||
val declarationLevelJsModules = mutableListOf<IrDeclarationWithName>()
|
||||
|
||||
private val internalPackageFragmentDescriptor = EmptyPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.js.internal"))
|
||||
val implicitDeclarationFile by lazy2 {
|
||||
val implicitDeclarationFile = run {
|
||||
IrFileImpl(object : SourceManager.FileEntry {
|
||||
override val name = "<implicitDeclarations>"
|
||||
override val maxOffset = UNDEFINED_OFFSET
|
||||
@@ -125,8 +125,6 @@ class JsIrBackendContext(
|
||||
implicitDeclarationFile.declarations += this
|
||||
}
|
||||
|
||||
override val sharedVariablesManager = JsSharedVariablesManager(irBuiltIns, implicitDeclarationFile)
|
||||
|
||||
override val mapping = JsMapping()
|
||||
override val declarationFactory = JsDeclarationFactory(mapping)
|
||||
|
||||
@@ -162,8 +160,11 @@ class JsIrBackendContext(
|
||||
private val coroutinePackage = module.getPackage(COROUTINE_PACKAGE_FQNAME)
|
||||
private val coroutineIntrinsicsPackage = module.getPackage(COROUTINE_INTRINSICS_PACKAGE_FQNAME)
|
||||
|
||||
val dynamicType: IrDynamicType = IrDynamicTypeImpl(null, emptyList(), Variance.INVARIANT)
|
||||
val intrinsics = JsIntrinsics(irBuiltIns, this)
|
||||
|
||||
override val sharedVariablesManager = JsSharedVariablesManager(this)
|
||||
|
||||
override val internalPackageFqn = JS_PACKAGE_FQNAME
|
||||
|
||||
private val operatorMap = referenceOperators()
|
||||
@@ -176,8 +177,6 @@ class JsIrBackendContext(
|
||||
return numbers + listOf(Name.identifier("String"), Name.identifier("Boolean"))
|
||||
}
|
||||
|
||||
val dynamicType: IrDynamicType = IrDynamicTypeImpl(null, emptyList(), Variance.INVARIANT)
|
||||
|
||||
fun getOperatorByName(name: Name, type: IrSimpleType) = operatorMap[name]?.get(type.classifier)
|
||||
|
||||
override val ir = object : Ir<JsIrBackendContext>(this, irModuleFragment) {
|
||||
|
||||
@@ -5,34 +5,25 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.DeclarationFactory
|
||||
import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||
import org.jetbrains.kotlin.ir.expressions.IrSetVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class JsSharedVariablesManager(val builtIns: IrBuiltIns, val implicitDeclarationsFile: IrPackageFragment) : SharedVariablesManager {
|
||||
class JsSharedVariablesManager(context: JsIrBackendContext) : SharedVariablesManager {
|
||||
|
||||
private val builtIns: IrBuiltIns = context.irBuiltIns
|
||||
private val createBox: IrSimpleFunctionSymbol = context.intrinsics.createSharedBox.symbol
|
||||
private val readBox: IrSimpleFunctionSymbol = context.intrinsics.readSharedBox.symbol
|
||||
private val writeBox: IrSimpleFunctionSymbol = context.intrinsics.writeSharedBox.symbol
|
||||
private val dynamicType = context.dynamicType
|
||||
|
||||
override fun declareSharedVariable(originalDeclaration: IrVariable): IrVariable {
|
||||
val valueType = originalDeclaration.type
|
||||
@@ -42,16 +33,14 @@ class JsSharedVariablesManager(val builtIns: IrBuiltIns, val implicitDeclaration
|
||||
valueType
|
||||
)
|
||||
|
||||
val constructorSymbol = closureBoxConstructorDeclaration.symbol
|
||||
|
||||
val irCall =
|
||||
IrConstructorCallImpl(
|
||||
IrCallImpl(
|
||||
initializer.startOffset, initializer.endOffset,
|
||||
closureBoxType, constructorSymbol,
|
||||
dynamicType, createBox,
|
||||
valueArgumentsCount = 1,
|
||||
typeArgumentsCount = 0,
|
||||
constructorTypeArgumentsCount = 0
|
||||
typeArgumentsCount = 1
|
||||
).apply {
|
||||
putTypeArgument(0, valueType)
|
||||
putValueArgument(0, initializer)
|
||||
}
|
||||
|
||||
@@ -62,7 +51,7 @@ class JsSharedVariablesManager(val builtIns: IrBuiltIns, val implicitDeclaration
|
||||
originalDeclaration.origin,
|
||||
IrVariableSymbolImpl(descriptor),
|
||||
originalDeclaration.name,
|
||||
irCall.type,
|
||||
dynamicType,
|
||||
isVar = false,
|
||||
isConst = false,
|
||||
isLateinit = false
|
||||
@@ -75,130 +64,51 @@ class JsSharedVariablesManager(val builtIns: IrBuiltIns, val implicitDeclaration
|
||||
|
||||
override fun defineSharedValue(originalDeclaration: IrVariable, sharedVariableDeclaration: IrVariable) = sharedVariableDeclaration
|
||||
|
||||
override fun getSharedValue(sharedVariableSymbol: IrVariableSymbol, originalGet: IrGetValue) = IrGetFieldImpl(
|
||||
originalGet.startOffset, originalGet.endOffset,
|
||||
closureBoxFieldDeclaration.symbol,
|
||||
originalGet.type,
|
||||
IrGetValueImpl(
|
||||
override fun getSharedValue(sharedVariableSymbol: IrVariableSymbol, originalGet: IrGetValue): IrExpression {
|
||||
|
||||
return IrCallImpl(
|
||||
originalGet.startOffset,
|
||||
originalGet.endOffset,
|
||||
closureBoxType,
|
||||
sharedVariableSymbol,
|
||||
originalGet.type,
|
||||
readBox,
|
||||
typeArgumentsCount = 1,
|
||||
valueArgumentsCount = 1,
|
||||
originalGet.origin
|
||||
),
|
||||
originalGet.origin
|
||||
)
|
||||
|
||||
override fun setSharedValue(sharedVariableSymbol: IrVariableSymbol, originalSet: IrSetVariable): IrExpression =
|
||||
IrSetFieldImpl(
|
||||
originalSet.startOffset,
|
||||
originalSet.endOffset,
|
||||
closureBoxFieldDeclaration.symbol,
|
||||
IrGetValueImpl(
|
||||
originalSet.startOffset,
|
||||
originalSet.endOffset,
|
||||
closureBoxType,
|
||||
sharedVariableSymbol,
|
||||
originalSet.origin
|
||||
),
|
||||
originalSet.value,
|
||||
originalSet.type,
|
||||
originalSet.origin
|
||||
)
|
||||
|
||||
private val boxTypeName = "\$closureBox\$"
|
||||
|
||||
private val closureBoxClassDeclaration by lazy {
|
||||
createClosureBoxClassDeclaration()
|
||||
}
|
||||
|
||||
private val closureBoxConstructorDeclaration by lazy {
|
||||
createClosureBoxConstructorDeclaration()
|
||||
}
|
||||
|
||||
private val closureBoxFieldDeclaration by lazy {
|
||||
closureBoxPropertyDeclaration
|
||||
}
|
||||
|
||||
private val closureBoxPropertyDeclaration by lazy {
|
||||
createClosureBoxPropertyDeclaration()
|
||||
}
|
||||
|
||||
private lateinit var closureBoxType: IrType
|
||||
|
||||
private fun createClosureBoxClassDeclaration(): IrClass {
|
||||
val descriptor = WrappedClassDescriptor()
|
||||
val declaration = IrClassImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, JsLoweredDeclarationOrigin.JS_CLOSURE_BOX_CLASS_DECLARATION, IrClassSymbolImpl(descriptor),
|
||||
Name.identifier(boxTypeName), ClassKind.CLASS, Visibilities.PUBLIC, Modality.FINAL
|
||||
)
|
||||
|
||||
descriptor.bind(declaration)
|
||||
declaration.parent = implicitDeclarationsFile
|
||||
// TODO: substitute
|
||||
closureBoxType = IrSimpleTypeImpl(declaration.symbol, false, emptyList(), emptyList())
|
||||
declaration.thisReceiver =
|
||||
JsIrBuilder.buildValueParameter(Name.special("<this>"), -1, closureBoxType, IrDeclarationOrigin.INSTANCE_RECEIVER).apply {
|
||||
parent = declaration
|
||||
}
|
||||
implicitDeclarationsFile.declarations += declaration
|
||||
|
||||
return declaration
|
||||
}
|
||||
|
||||
private fun createClosureBoxPropertyDeclaration(): IrField {
|
||||
val descriptor = WrappedFieldDescriptor()
|
||||
val symbol = IrFieldSymbolImpl(descriptor)
|
||||
val fieldName = Name.identifier("v")
|
||||
return IrFieldImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
DeclarationFactory.FIELD_FOR_OUTER_THIS,
|
||||
symbol,
|
||||
fieldName,
|
||||
builtIns.anyNType,
|
||||
Visibilities.PUBLIC,
|
||||
isFinal = false,
|
||||
isExternal = false,
|
||||
isStatic = false
|
||||
).also {
|
||||
descriptor.bind(it)
|
||||
it.parent = closureBoxClassDeclaration
|
||||
closureBoxClassDeclaration.declarations += it
|
||||
).apply {
|
||||
putTypeArgument(0, originalGet.type)
|
||||
putValueArgument(
|
||||
0, IrGetValueImpl(
|
||||
originalGet.startOffset,
|
||||
originalGet.endOffset,
|
||||
dynamicType,
|
||||
sharedVariableSymbol,
|
||||
originalGet.origin
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createClosureBoxConstructorDeclaration(): IrConstructor {
|
||||
val descriptor = WrappedClassConstructorDescriptor()
|
||||
val symbol = IrConstructorSymbolImpl(descriptor)
|
||||
|
||||
val declaration = IrConstructorImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, JsLoweredDeclarationOrigin.JS_CLOSURE_BOX_CLASS_DECLARATION, symbol,
|
||||
Name.special("<init>"), Visibilities.PUBLIC, closureBoxClassDeclaration.defaultType,
|
||||
isInline = false, isExternal = false, isPrimary = true, isExpect = false
|
||||
)
|
||||
|
||||
descriptor.bind(declaration)
|
||||
declaration.parent = closureBoxClassDeclaration
|
||||
|
||||
val parameterDeclaration = createClosureBoxConstructorParameterDeclaration(declaration)
|
||||
|
||||
declaration.valueParameters += parameterDeclaration
|
||||
|
||||
val receiver = JsIrBuilder.buildGetValue(closureBoxClassDeclaration.thisReceiver!!.symbol)
|
||||
val value = JsIrBuilder.buildGetValue(parameterDeclaration.symbol)
|
||||
|
||||
val setField = JsIrBuilder.buildSetField(closureBoxFieldDeclaration.symbol, receiver, value, closureBoxFieldDeclaration.type)
|
||||
|
||||
declaration.body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf(setField))
|
||||
|
||||
closureBoxClassDeclaration.declarations += declaration
|
||||
return declaration
|
||||
}
|
||||
|
||||
private fun createClosureBoxConstructorParameterDeclaration(irConstructor: IrConstructor): IrValueParameter {
|
||||
return JsIrBuilder.buildValueParameter("p", 0, closureBoxPropertyDeclaration.type).also {
|
||||
it.parent = irConstructor
|
||||
override fun setSharedValue(sharedVariableSymbol: IrVariableSymbol, originalSet: IrSetVariable): IrExpression {
|
||||
return IrCallImpl(
|
||||
originalSet.startOffset,
|
||||
originalSet.endOffset,
|
||||
builtIns.unitType,
|
||||
writeBox,
|
||||
typeArgumentsCount = 1,
|
||||
valueArgumentsCount = 2,
|
||||
originalSet.origin
|
||||
).apply {
|
||||
putTypeArgument(0, originalSet.value.type)
|
||||
putValueArgument(
|
||||
0, IrGetValueImpl(
|
||||
originalSet.startOffset,
|
||||
originalSet.endOffset,
|
||||
dynamicType,
|
||||
sharedVariableSymbol,
|
||||
originalSet.origin
|
||||
)
|
||||
)
|
||||
putValueArgument(1, originalSet.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,6 +218,23 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
|
||||
add(intrinsics.unreachable) { _, _ ->
|
||||
JsInvocation(JsNameRef(Namer.UNREACHABLE_NAME))
|
||||
}
|
||||
|
||||
add(intrinsics.createSharedBox) { call, context: JsGenerationContext ->
|
||||
val arg = translateCallArguments(call, context).single()
|
||||
JsObjectLiteral(listOf(JsPropertyInitializer(JsNameRef(Namer.SHARED_BOX_V), arg)))
|
||||
}
|
||||
|
||||
add(intrinsics.readSharedBox) { call, context: JsGenerationContext ->
|
||||
val box = translateCallArguments(call, context).single()
|
||||
JsNameRef(Namer.SHARED_BOX_V, box)
|
||||
}
|
||||
|
||||
add(intrinsics.writeSharedBox) { call, context: JsGenerationContext ->
|
||||
val args = translateCallArguments(call, context)
|
||||
val box = args[0]
|
||||
val value = args[1]
|
||||
jsAssignment(JsNameRef(Namer.SHARED_BOX_V, box), value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.utils
|
||||
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsNameRef
|
||||
|
||||
object Namer {
|
||||
@@ -43,4 +42,6 @@ object Namer {
|
||||
val KPROPERTY_SET = "set"
|
||||
val KCALLABLE_CACHE_SUFFIX = "\$cache"
|
||||
const val KCALLABLE_ARITY = "\$arity"
|
||||
|
||||
const val SHARED_BOX_V = "_v"
|
||||
}
|
||||
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_DEFAULT_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_DEFAULT_NO_COMPATIBILITY_FQ_NAME
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||
|
||||
/**
|
||||
@@ -164,6 +165,7 @@ fun IrSimpleFunction.isCompiledToJvmDefault(jvmDefaultMode: JvmDefaultMode): Boo
|
||||
}
|
||||
|
||||
fun IrFunction.hasJvmDefault(): Boolean = propertyIfAccessor.hasAnnotation(JVM_DEFAULT_FQ_NAME)
|
||||
fun IrClass.hasJvmDefaultNoCompatibilityAnnotation(): Boolean = hasAnnotation(JVM_DEFAULT_NO_COMPATIBILITY_FQ_NAME)
|
||||
fun IrFunction.hasPlatformDependent(): Boolean = propertyIfAccessor.hasAnnotation(PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME)
|
||||
|
||||
fun IrFunction.getJvmVisibilityOfDefaultArgumentStub() =
|
||||
|
||||
@@ -62,6 +62,7 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
|
||||
|
||||
private fun handleInterface(irClass: IrClass) {
|
||||
val jvmDefaultMode = context.state.jvmDefaultMode
|
||||
val isCompatibilityMode = jvmDefaultMode.isCompatibility && !irClass.hasJvmDefaultNoCompatibilityAnnotation()
|
||||
// There are 6 cases for functions on interfaces:
|
||||
loop@ for (function in irClass.functions) {
|
||||
when {
|
||||
@@ -112,7 +113,7 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
|
||||
defaultImpl.bridgeToStatic(it)
|
||||
}
|
||||
}
|
||||
jvmDefaultMode.isCompatibility && implementation.isCompiledToJvmDefault(jvmDefaultMode) -> {
|
||||
isCompatibilityMode && implementation.isCompiledToJvmDefault(jvmDefaultMode) -> {
|
||||
val defaultImpl = createDefaultImpl(function)
|
||||
defaultImpl.bridgeViaAccessorTo(function)
|
||||
}
|
||||
@@ -145,7 +146,7 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
|
||||
/**
|
||||
* 5) JVM default declaration is bridged in DefaultImpls via accessor if in compatibility mode, ...
|
||||
*/
|
||||
jvmDefaultMode.isCompatibility -> {
|
||||
isCompatibilityMode -> {
|
||||
val defaultImpl = createDefaultImpl(function)
|
||||
defaultImpl.bridgeViaAccessorTo(function)
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ class WasmBackendContext(
|
||||
builtIns.builtInsModule, FqName("kotlin.wasm.internal")
|
||||
)
|
||||
|
||||
override val sharedVariablesManager = JsSharedVariablesManager(irBuiltIns, internalPackageFragment)
|
||||
override val sharedVariablesManager = JsSharedVariablesManager(TODO("..."))
|
||||
|
||||
val wasmSymbols: WasmSymbols = WasmSymbols(this@WasmBackendContext, symbolTable)
|
||||
override val ir = object : Ir<WasmBackendContext>(this, irModuleFragment) {
|
||||
|
||||
@@ -64,19 +64,22 @@ object SamTypeConversions : ParameterTypeConversion {
|
||||
val callComponents = candidate.callComponents
|
||||
val originalExpectedType = argument.getExpectedType(parameter.original, callComponents.languageVersionSettings)
|
||||
|
||||
val convertedTypeByOriginal =
|
||||
callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(
|
||||
originalExpectedType,
|
||||
callComponents.samConversionOracle
|
||||
) ?: return null
|
||||
|
||||
val convertedTypeByCandidate =
|
||||
callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(
|
||||
expectedParameterType,
|
||||
callComponents.samConversionOracle
|
||||
)
|
||||
) ?: return null
|
||||
|
||||
assert(expectedParameterType.constructor == originalExpectedType.constructor && convertedTypeByCandidate != null) {
|
||||
val convertedTypeByOriginal =
|
||||
if (expectedParameterType.constructor == originalExpectedType.constructor)
|
||||
callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(
|
||||
originalExpectedType,
|
||||
callComponents.samConversionOracle
|
||||
)
|
||||
else
|
||||
convertedTypeByCandidate
|
||||
|
||||
assert(convertedTypeByCandidate.constructor == convertedTypeByOriginal?.constructor) {
|
||||
"If original type is SAM type, then candidate should have same type constructor and corresponding function type\n" +
|
||||
"originalExpectType: $originalExpectedType, candidateExpectType: $expectedParameterType\n" +
|
||||
"functionTypeByOriginal: $convertedTypeByOriginal, functionTypeByCandidate: $convertedTypeByCandidate"
|
||||
@@ -84,7 +87,7 @@ object SamTypeConversions : ParameterTypeConversion {
|
||||
|
||||
candidate.resolvedCall.registerArgumentWithSamConversion(
|
||||
argument,
|
||||
SamConversionDescription(convertedTypeByOriginal, convertedTypeByCandidate!!)
|
||||
SamConversionDescription(convertedTypeByOriginal!!, convertedTypeByCandidate)
|
||||
)
|
||||
|
||||
if (needCompatibilityResolveForSAM(candidate, expectedParameterType)) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeApproximator
|
||||
|
||||
@@ -44,6 +45,11 @@ interface ImplicitScopeTower {
|
||||
|
||||
val typeApproximator: TypeApproximator
|
||||
|
||||
val implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter
|
||||
|
||||
fun allScopesWithImplicitsResolutionInfo(): Sequence<ScopeWithImplicitsExtensionsResolutionInfo> =
|
||||
implicitsResolutionFilter.getScopesWithInfo(lexicalScope.parentsWithSelf)
|
||||
|
||||
fun interceptFunctionCandidates(
|
||||
resolutionScope: ResolutionScope,
|
||||
name: Name,
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation
|
||||
import org.jetbrains.kotlin.resolve.scopes.HierarchicalScope
|
||||
|
||||
@DefaultImplementation(ImplicitsExtensionsResolutionFilter.Default::class)
|
||||
interface ImplicitsExtensionsResolutionFilter {
|
||||
fun getScopesWithInfo(
|
||||
scopes: Sequence<HierarchicalScope>
|
||||
): Sequence<ScopeWithImplicitsExtensionsResolutionInfo>
|
||||
|
||||
object Default : ImplicitsExtensionsResolutionFilter {
|
||||
override fun getScopesWithInfo(
|
||||
scopes: Sequence<HierarchicalScope>
|
||||
): Sequence<ScopeWithImplicitsExtensionsResolutionInfo> = scopes.map { scope ->
|
||||
ScopeWithImplicitsExtensionsResolutionInfo(scope, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ScopeWithImplicitsExtensionsResolutionInfo(
|
||||
val scope: HierarchicalScope,
|
||||
val resolveExtensionsForImplicitReceiver: Boolean,
|
||||
)
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
|
||||
import org.jetbrains.kotlin.resolve.scopes.HierarchicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.ResolutionScope
|
||||
@@ -185,7 +186,7 @@ class TowerResolver {
|
||||
TowerData.TowerLevel(localLevel).process()?.let { return it }
|
||||
}
|
||||
|
||||
for (scope in implicitScopeTower.lexicalScope.parentsWithSelf) {
|
||||
fun processScope(scope: HierarchicalScope, resolveExtensionsForImplicitReceiver: Boolean): Collection<C>? {
|
||||
if (scope is LexicalScope) {
|
||||
// statics
|
||||
if (!scope.kind.withLocalDescriptors) {
|
||||
@@ -194,12 +195,23 @@ class TowerResolver {
|
||||
}
|
||||
|
||||
implicitScopeTower.getImplicitReceiver(scope)
|
||||
?.let(this::processImplicitReceiver)
|
||||
?.let { processImplicitReceiver(it, resolveExtensionsForImplicitReceiver) }
|
||||
?.let { return it }
|
||||
} else {
|
||||
TowerData.TowerLevel(ImportingScopeBasedTowerLevel(implicitScopeTower, scope as ImportingScope))
|
||||
.process(scope.mayFitForName(name))?.let { return it }
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
if (implicitScopeTower.implicitsResolutionFilter === ImplicitsExtensionsResolutionFilter.Default) {
|
||||
for (scope in implicitScopeTower.lexicalScope.parentsWithSelf) {
|
||||
processScope(scope, true)?.let { return it }
|
||||
}
|
||||
} else {
|
||||
for (scopeInfo in implicitScopeTower.allScopesWithImplicitsResolutionInfo()) {
|
||||
processScope(scopeInfo.scope, scopeInfo.resolveExtensionsForImplicitReceiver)?.let { return it }
|
||||
}
|
||||
}
|
||||
|
||||
recordLookups()
|
||||
@@ -207,7 +219,7 @@ class TowerResolver {
|
||||
return resultCollector.getFinalCandidates()
|
||||
}
|
||||
|
||||
private fun processImplicitReceiver(implicitReceiver: ReceiverValueWithSmartCastInfo): Collection<C>? {
|
||||
private fun processImplicitReceiver(implicitReceiver: ReceiverValueWithSmartCastInfo, resolveExtensions: Boolean): Collection<C>? {
|
||||
if (isNameForHidesMember) {
|
||||
// hides members extensions
|
||||
TowerData.BothTowerLevelAndImplicitReceiver(hidesMembersLevel, implicitReceiver).process()?.let { return it }
|
||||
@@ -220,17 +232,19 @@ class TowerResolver {
|
||||
// synthetic properties
|
||||
TowerData.BothTowerLevelAndImplicitReceiver(syntheticLevel, implicitReceiver).process()?.let { return it }
|
||||
|
||||
// invokeExtension on local variable
|
||||
TowerData.OnlyImplicitReceiver(implicitReceiver).process()?.let { return it }
|
||||
if (resolveExtensions) {
|
||||
// invokeExtension on local variable
|
||||
TowerData.OnlyImplicitReceiver(implicitReceiver).process()?.let { return it }
|
||||
|
||||
// local extensions for implicit receiver
|
||||
for (localLevel in localLevels) {
|
||||
TowerData.BothTowerLevelAndImplicitReceiver(localLevel, implicitReceiver).process()?.let { return it }
|
||||
}
|
||||
// local extensions for implicit receiver
|
||||
for (localLevel in localLevels) {
|
||||
TowerData.BothTowerLevelAndImplicitReceiver(localLevel, implicitReceiver).process()?.let { return it }
|
||||
}
|
||||
|
||||
// extension for implicit receiver
|
||||
for (nonLocalLevel in nonLocalLevels) {
|
||||
TowerData.BothTowerLevelAndImplicitReceiver(nonLocalLevel, implicitReceiver).process()?.let { return it }
|
||||
// extension for implicit receiver
|
||||
for (nonLocalLevel in nonLocalLevels) {
|
||||
TowerData.BothTowerLevelAndImplicitReceiver(nonLocalLevel, implicitReceiver).process()?.let { return it }
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
|
||||
@@ -91,6 +91,14 @@ class LexicalChainedScope private constructor(
|
||||
p.println("}")
|
||||
}
|
||||
|
||||
override fun definitelyDoesNotContainName(name: Name): Boolean {
|
||||
return memberScopes.all { it.definitelyDoesNotContainName(name) }
|
||||
}
|
||||
|
||||
override fun recordLookup(name: Name, location: LookupLocation) {
|
||||
memberScopes.forEach { it.recordLookup(name, location) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmOverloads
|
||||
|
||||
@@ -4,9 +4,9 @@ public interface B extends p.A {
|
||||
|
||||
static final class DefaultImpls {
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public static java.lang.String b(p.B $this) { /* compiled code */ }
|
||||
public static java.lang.String b(@org.jetbrains.annotations.NotNull p.B $this) { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public static java.lang.String a(p.B $this) { /* compiled code */ }
|
||||
public static java.lang.String a(@org.jetbrains.annotations.NotNull p.B $this) { /* compiled code */ }
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,8 @@ fun box(): String {
|
||||
receiver = { invokeOrder += " receiver"; "R" }()
|
||||
)
|
||||
if (result != "C, R, I") return "fail 3: $result"
|
||||
if (invokeOrder != "init constraints receiver") return "fail 4: $invokeOrder"
|
||||
// Change test after e3fe1bcf7c3 has been dealt with.
|
||||
if (invokeOrder != "init receiver constraints") return "fail 4: $invokeOrder"
|
||||
|
||||
result = ""
|
||||
invokeOrder = ""
|
||||
|
||||
@@ -5,16 +5,16 @@ fun box(): String {
|
||||
val intList = listOf(1, 2, 3)
|
||||
val longList = listOf(1L, 2L, 3L)
|
||||
|
||||
val intListMin = intList.minBy { it }
|
||||
val intListMin = intList.minByOrNull { it }
|
||||
if (intListMin != 1) return "Fail intListMin=$intListMin"
|
||||
|
||||
val intListMax = intList.maxBy { it }
|
||||
val intListMax = intList.maxByOrNull { it }
|
||||
if (intListMax != 3) return "Fail intListMax=$intListMax"
|
||||
|
||||
val longListMin = longList.minBy { it }
|
||||
val longListMin = longList.minByOrNull { it }
|
||||
if (longListMin != 1L) return "Fail longListMin=$longListMin"
|
||||
|
||||
val longListMax = longList.maxBy { it }
|
||||
val longListMax = longList.maxByOrNull { it }
|
||||
if (longListMax != 3L) return "Fail longListMax=$longListMax"
|
||||
|
||||
return "OK"
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
fun foo(): Array<Boolean> {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
fun foo(): Array<Boolean> {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
5
compiler/testData/codegen/box/enum/kt38996.kt
vendored
Normal file
5
compiler/testData/codegen/box/enum/kt38996.kt
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
enum class E(val b: Boolean) {
|
||||
TRUE(1 == 1)
|
||||
}
|
||||
|
||||
fun box() = if (E.TRUE.b) "OK" else "fail"
|
||||
@@ -1,6 +1,6 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// IGNORE_BACKEND: JS_IR_ES6
|
||||
// SKIP_DCE_DRIVEN
|
||||
|
||||
fun interface FunWithReceiver {
|
||||
fun String.foo(): String
|
||||
|
||||
22
compiler/testData/codegen/box/inference/plusAssignInsideLambda.kt
vendored
Normal file
22
compiler/testData/codegen/box/inference/plusAssignInsideLambda.kt
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.experimental.ExperimentalTypeInference
|
||||
|
||||
interface SendChannel<in T> {
|
||||
suspend fun send(value: T)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTypeInference::class)
|
||||
public fun <T> flux(@BuilderInference block: suspend SendChannel<T>.() -> Unit) {}
|
||||
|
||||
suspend inline fun <T> T.collect(action: (T) -> Unit) { action(this) }
|
||||
|
||||
fun test() {
|
||||
flux {
|
||||
var result = ""
|
||||
"OK".collect { result += it }
|
||||
send(result)
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = "OK"
|
||||
@@ -1,5 +1,3 @@
|
||||
// TODO: new inference doesn't do SAM conversion in this case. KT-37149
|
||||
// !LANGUAGE: -NewInference
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// FILE: Generic.java
|
||||
|
||||
@@ -9,6 +9,7 @@ interface Z<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmDefaultWithoutCompatibility
|
||||
open class ZImpl : Z<String>
|
||||
|
||||
class ZImpl2 : ZImpl() {
|
||||
|
||||
@@ -9,8 +9,11 @@ interface Z<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmDefaultWithoutCompatibility
|
||||
open class ZImpl : Z<String>
|
||||
|
||||
//TODO: this is redundant, revise diagnostic
|
||||
@JvmDefaultWithoutCompatibility
|
||||
open class ZImpl2 : Z<String>, ZImpl()
|
||||
|
||||
class ZImpl3 : ZImpl2() {
|
||||
|
||||
18
compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/specialization/basic.kt
vendored
Normal file
18
compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/specialization/basic.kt
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// !JVM_DEFAULT_MODE: all
|
||||
// JVM_TARGET: 1.8
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
interface Foo<T> {
|
||||
fun test(p: T) = p
|
||||
val T.prop: T
|
||||
get() = this
|
||||
}
|
||||
|
||||
open class BaseSpecialized : Foo<String> {
|
||||
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val base = BaseSpecialized()
|
||||
return base.test("O") + with(base) { "K".prop }
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun inInt(x: Long): Boolean {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// IGNORE_BACKEND: JS_IR_ES6
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun box(): String {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TODO: investigate should it be ran for JS or not
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user