Compare commits

...

97 Commits

Author SHA1 Message Date
Dmitriy Dolovov
59183a8142 [Commonizer] Replace j.u.HashMap by g.t.THashMap to reduce memory usage 2020-06-19 19:36:06 +07:00
Dmitriy Dolovov
70ea53315d [Commonizer] Intern duplicated CirContainingClassDetails instances 2020-06-19 19:18:13 +07:00
Dmitriy Dolovov
63d549dfa1 [Commonizer] Intern duplicated CirFunctionModifiers instances 2020-06-19 19:18:07 +07:00
Dmitriy Dolovov
68e1acd2cb [Commonizer] More detailed progress logging 2020-06-19 19:18:01 +07:00
Dmitriy Dolovov
6410aed1b4 Minor. Replace computeIfAbsent() by getOrPut() 2020-06-19 19:17:55 +07:00
Dmitriy Dolovov
6393667dda [Commonizer] Rework preparation of CIR cache in TypeCommonizerTest 2020-06-19 19:17:49 +07:00
Dmitriy Dolovov
5cad8a793c [Commonizer] Rework CommonizedGroup API to make it more usable 2020-06-19 19:17:43 +07:00
Dmitriy Dolovov
63575582c4 [Commonizer] Reduce memory consumption during approximation phase
^KT-39320
2020-06-19 19:17:33 +07:00
Ilya Chernikov
d5ffc7416d Clean-up and improve sam-with-receiver test with scripts 2020-06-19 14:08:19 +02:00
Ilya Chernikov
0ade8140f7 Add serialization plugin test with main-kts 2020-06-19 14:08:19 +02:00
Ilya Chernikov
dbb47cf48e Implement non-transitive dependencies resolving in main-kts 2020-06-19 14:08:19 +02:00
Ilya Chernikov
cd1bf563cd Add error reporting on the options parsing errors in scripting
also report standard parsing warnings
also fix language version test, since it is not possible anymore
  to use version 1.0
2020-06-19 13:20:58 +02:00
Mathias Quintero
f0bc52222d Fix annotation construction with array literals
Turns out the issue happens to be that ArrayValue uses a list of values which needs to be translated to an array of the percise type before it is used by callBy

This also addresses handling of arguments after a vararg in an annotation
2020-06-19 13:20:57 +02:00
Efeturi Money
8cb4f59114 Explicitly handle array annotation args in scripting pre-processing
#KT-35411 fixed
2020-06-19 13:20:57 +02:00
Ilya Muradyan
743abea690 Don't create default importing scopes for REPL snippets
Default scopes should be created only once, for the first snippet.
All following snippets should not create new default importing scopes.
#KT-35651 fixed
2020-06-19 13:03:25 +02:00
Ilya Muradyan
c3cbfe34c4 Allow not to create default importing scopes 2020-06-19 13:03:24 +02:00
Ilya Muradyan
53b31a20ca Refactor REPL IDE services testing configuration and add new tests 2020-06-19 13:03:24 +02:00
Ilya Muradyan
94de114894 Support selective filtering of implicits for extensions resolution in REPL 2020-06-19 13:03:23 +02:00
Ilya Muradyan
017f640f26 Allow skipping extensions resolution for implicit receivers 2020-06-19 13:03:23 +02:00
Mikhail Bogdanov
e93bcc55ae Revert "Deprecate DefaultImpl methods in compatibility mode"
This reverts commit 6c9c2a28
2020-06-19 12:58:46 +02:00
Mikhail Bogdanov
8bc4407be0 Fix compilation 2020-06-19 12:54:19 +02:00
Mikhail Bogdanov
6c9c2a287d Deprecate DefaultImpl methods in compatibility mode 2020-06-19 12:23:05 +02:00
Mikhail Bogdanov
9c0b96af71 Report error on missed specialization in compatibility mode
#KT-39603 Fixed
2020-06-19 11:57:36 +02:00
Mikhail Bogdanov
a150e7b6e5 Don't forget about extension parameter in methodSignatureMapping.kt 2020-06-19 11:57:36 +02:00
Mikhail Bogdanov
929bb0e8d1 Move common logic from CodegenTestCase to KotlinBaseTest 2020-06-19 11:57:36 +02:00
Mikhail Bogdanov
9d48ecfac3 Make proper check for defaults on delegation to DefaultImpls 2020-06-19 11:57:36 +02:00
Mikhail Bogdanov
b8f0ad2111 Generate nullability annotations on this receiver in DefaultImpls. Don't generate nullability annotations in private methods
#KT-36969 Fixed
2020-06-19 11:57:35 +02:00
Mikhail Bogdanov
5bdf3d5757 Don't generate compatibility stubs for @JvmDefaultWithoutCompatibility 2020-06-19 11:57:35 +02:00
Mikhail Bogdanov
477cca3c99 Add JvmDefaultWithoutCompatibility annotation 2020-06-19 11:57:35 +02:00
Dmitriy Novozhilov
a98ad79d86 [FIR-TEST] Add option to run modularized tests with checkers 2020-06-19 12:40:02 +03:00
Dmitriy Novozhilov
7a8908a75b [FIR-TEST] Change main module of [JPS] Fast FIR tests task
It's needed to correctly run FIR spec tests
2020-06-19 12:40:01 +03:00
Roman Artemev
a0cccdf75c [JS IR] Make backend work with new shared boxes 2020-06-19 12:23:15 +03:00
Roman Artemev
596c3d1af8 [JS IR] Implement shared box intrinsics translator 2020-06-19 12:23:15 +03:00
Roman Artemev
4c878c27a9 [JS IR] Introduce intrinsics to create shared boxes 2020-06-19 12:23:15 +03:00
Dmitry Savvinov
5b48845dfa Check for native-shared source-sets properly during facet import
Otherwise they are detected as common source-sets, thus getting
K2MetadataCompilerArguments (instead of FakeK2NativeCompilerArguments),
and the 'applyCompilerArgumentsToFacets' will fail due to check on
javaClass equality

^KT-39657 Fixed
2020-06-19 12:15:50 +03:00
Ilya Goncharov
ce553f1211 [Gradle, JS] Add webpackConfig for karma
#KT-39654 fixed
2020-06-19 11:38:51 +03:00
Ilya Goncharov
48a4e08d60 [Gradle, JS] Disable css support by default
#KT-39654 fixed
2020-06-19 11:38:31 +03:00
Denis Zharkov
efee0dae94 FIR: Simplify JvmBinaryAnnotationDeserializer
Currently, it's anyway created one per class
2020-06-19 10:21:09 +03:00
Denis Zharkov
0bc2642634 FIR: Add clarification to the workaround for KT-39659 2020-06-19 10:21:09 +03:00
Denis Zharkov
429b2a9705 FIR: Optimize deserialized annotations loading 2020-06-19 10:21:09 +03:00
Denis Zharkov
260e2d0dc3 FIR: Add dependency for :core:descriptors.runtime to modularized tests
Otherwise NoClassDefFoundError happens on JPS
2020-06-19 10:21:09 +03:00
Jinseong Jeon
6a28558d43 FIR deserializer: rename a callable kind that represents all "others" 2020-06-19 10:21:09 +03:00
Jinseong Jeon
12181e55c0 FIR deserializer: signature-aware annotation loading for constructors 2020-06-19 10:21:09 +03:00
Jinseong Jeon
955c7a1e5b FIR2IR: handle deserialized class reference inside GetClassCall 2020-06-19 10:21:09 +03:00
Jinseong Jeon
781bfa20e8 FIR deserializer: fix conversion of class literal inside annotation array value. 2020-06-19 10:21:09 +03:00
Jinseong Jeon
b076bec07f FIR deserializer: signature-aware annotation loading for functions 2020-06-19 10:21:09 +03:00
Ilya Kirillov
11a680d7d8 Wizard: group project templates into the categories on the first step
#KT-39700 fixed
2020-06-19 09:29:41 +03:00
Ilya Kirillov
bfedeed2c1 Wizard: use new icons in UI 2020-06-19 09:29:40 +03:00
Ilya Kirillov
7df0dd5032 Wizard: fix ui constants 2020-06-19 09:29:39 +03:00
Abduqodiri Qurbonzoda
6e5b94f695 Update js public api dump 2020-06-19 08:39:48 +03:00
Abduqodiri Qurbonzoda
c923b2e139 Deprecate contains, indexOf, lastIndexOf functions of Float/DoubleArray #KT-28753 2020-06-19 08:39:47 +03:00
Abduqodiri Qurbonzoda
97c688057d Compare floating point values asList elements in total order #KT-28753 2020-06-19 08:39:47 +03:00
Toshiaki Kameyama
ba5e643cb2 Redundant qualifier name: fix false positive with same name variable
#KT-39200 Fixed
2020-06-19 12:08:36 +07:00
Abduqodiri Qurbonzoda
bf26d87ee9 Update js public api dump 2020-06-19 04:53:54 +03:00
Abduqodiri Qurbonzoda
16b62b8e65 Introduce minWithOrNull and maxWithOrNull extension functions #KT-38854 2020-06-19 04:53:53 +03:00
Abduqodiri Qurbonzoda
194791a168 Introduce minByOrNull and maxByOrNull extension functions #KT-38854 2020-06-19 04:53:51 +03:00
Abduqodiri Qurbonzoda
846a7823ad Introduce minOrNull and maxOrNull extension functions #KT-39064 2020-06-19 04:53:49 +03:00
simon.ogorodnik
a8cd8ad8f8 [FIR] Fix testData after changing anonymous object name 2020-06-19 01:52:02 +03:00
Vladimir Ilmov
b100fd526f (CoroutineDebugger)(Test) local variable removed from generated code 2020-06-19 00:32:19 +02:00
Vyacheslav Gerasimov
5724c47bcf Build: Fix uri parsing on windows in publication repo configuration 2020-06-19 00:35:55 +03:00
Ilmir Usmanov
542f1b8709 Minor. Update tests 2020-06-18 17:53:47 +02:00
Ilya Goncharov
932cf21776 [Gradle, JS] Allow to change destDir only for separate task and name it destinationDir
#KT-38331 fixed
2020-06-18 18:51:30 +03:00
Ilya Goncharov
7386408e94 [Gradle, JS] AbstractDukatTask -> DukatTask
#KT-38331 fixed
2020-06-18 18:51:08 +03:00
Ilya Goncharov
49dd839131 [Gradle, JS] DukatTask -> IntegratedDukatTask
#KT-38331 fixed
2020-06-18 18:50:53 +03:00
Ilya Goncharov
46be588f27 [Gradle, JS] Add task for separate usage of Dukat with project npm dependencies
#KT-38331 fixed
2020-06-18 18:50:36 +03:00
Ilya Gorbunov
606fad64ad Leave StringBuilder.append/insert with non-nullable String parameter
Leave these methods as hidden in order to preserve binary compatibility.

#KT-39504
2020-06-18 18:45:43 +03:00
Pavel Kirpichenkov
91b371789e Invalidate library caches on OOCBM with enabled resolution anchors
Without forced clean stale references to declarations from source-dependent libraries
can be accessed after invalidation, i.e. resolved references can point to incorrect PSI.
TBD: more granular invalidation.

KT-24309
2020-06-18 18:27:28 +03:00
Alexander Udalov
204871a7ab Update bootstrap to 1.4.20-dev-772 2020-06-18 16:18:59 +02:00
Ilya Matveev
754a74ac4a [Gradle, native] Allow parallel in-process compiler execution
This commit allows parallel in-process execution of the K/N compiler
that was prohibited by 254a978a06.

Issue #KT-38991 fixed
2020-06-18 14:18:00 +00:00
Ilya Matveev
03bb9138ad [klib] Create ZipFileSystem from a Path instead of an URI
Calling FileSystems.newFileSystem(URI, ...) throws a
FileSystemAlreadyExistsException if a ZipFileSystem for this
URI is already created. We still can use a single instance
of ZipFileSystem by calling FileSystems.getFileSystem. In
this case we use reference counting to determine when this
instance can be safely closed.

But we cannot count references if the same ZipFileSystem is used
from different class loaders. This patch fixes this issue by
creating a file system from Path instead of an URI. Contract of
FileSystemProvider.newFileSystem(Path, ...) doesn't imply throwing
FileSystemAlreadyExistsException.

Issue #KT-37443 fixed
2020-06-18 14:17:59 +00:00
Natalia Selezneva
bf1ad44af9 Run partial import only for specified build root 2020-06-18 17:14:47 +03:00
Natalia Selezneva
5fe47ffbec Workaround for bug in GradleInstallationManager.resolveGradleVersion()
Wrong gradle version when wrapper is used
fixed in 201
2020-06-18 17:14:47 +03:00
Natalia Selezneva
7a47994498 Get gradle version and gradle home from corresponding BuildModel after import
GradleProjectSettings that were used, are updated after KotlinDslListener is called,
so it isn't correct to check if kotlinDslModels are supported using it.
Also GradleScriptDefinitionsContributor should use gradle home from BuildModel, not from settings for the same reasons.

^KT-39104 Fixed
2020-06-18 17:14:46 +03:00
Victor Petukhov
ece61915de NI: clean calls in coroutine inference before the second analysis of += only for right side
^KT-39660 Fixed
2020-06-18 17:09:59 +03:00
Vyacheslav Gerasimov
1f66049a1e Build: Fix plugin marker publication to a remote repository 2020-06-18 16:57:39 +03:00
Igor Chevdar
2fd657b768 [box-tests] Fixed test for K/N 2020-06-18 18:44:11 +05:00
Yan Zhulanow
8b5f2f9474 Fix duplicate stepping filter adding on plugin start-up (KT-38628)
Review KT-CR-1301.
2020-06-18 22:32:34 +09:00
Yan Zhulanow
235b9b9269 Add kotlin-stdlib-js and kotlin-test-js to IDE artifact dependencies 2020-06-18 22:32:34 +09:00
Pavel Kirpichenkov
470fef94fb Use bound resolution facade in DeprecationResolver usages
Resolution facade should be used consistently with direct usages of frontend components.
Otherwise they can start processing descriptors from foreign resolvers which leads to memory leaks.

Plain resolution API with provided facade is not suitable as-is for compiled declarations in KotlinIndicesHelper though.
Resolution facade for module sources contained in helper can't handle decompiled
sources from PSI indices (leads to "ModuleInfo not contained in resolver" errors).
That's why "hacked" resolve via import references should be used there.

#KT-39642 Fixed
2020-06-18 14:24:17 +03:00
Jinseong Jeon
82ef6bf96c FIR2IR: honor user-contributed members in data class if any 2020-06-18 14:23:52 +03:00
Mikhail Glukhikh
b839a91050 Mute 3 FIR BB tests due to LowPriorityInOverloadResolution in reflect
Recently second javaType function appeared in reflect and
now FIR can't correctly resolve the code :(.
Will be fixed after annotation deserialization full support
2020-06-18 13:39:48 +03:00
Mikhail Glukhikh
d009c90e3a Revert "Mute two FIR BB tests due to LowPriorityInOverloadResolution in reflect"
This reverts commit 3768af4f
2020-06-18 13:24:38 +03:00
Mikhail Glukhikh
3768af4f92 Mute two FIR BB tests due to LowPriorityInOverloadResolution in reflect
Recently second javaType function appeared in reflect and
now FIR can't correctly resolve the code :(.
Will be fixed after annotation deserialization full support
2020-06-18 13:21:35 +03:00
Mikhail Zarechenskiy
d44a7ff8f9 Add test for obsolete issue
The issue was fixed in df1595e

 #KT-39630 Fixed
2020-06-18 13:05:42 +03:00
Yan Zhulanow
559561ca6b Add missing intellij-core dependency for sam-with-receiver tests 2020-06-18 19:01:44 +09:00
Yan Zhulanow
713a305f45 Update change data for IrTextTestCaseGenerated
Reason of changes: 098469eb85
2020-06-18 19:01:06 +09:00
Ilya Gorbunov
ec5a04a6c7 Update public jvm API dump after introduction of javaType
See 9e37b62f62
2020-06-18 12:44:23 +03:00
Mikhail Zarechenskiy
a067d138e9 Enable test for new inference after df1595e4
Follow up KT-37149
2020-06-18 12:41:27 +03:00
Mikhail Zarechenskiy
df1595e4bc Fix SAM conversions for derived classes
#KT-39535 Fixed
 #KT-37149 Fixed
2020-06-18 12:36:30 +03:00
Georgy Bronnikov
ee6d432ced Add forgotten test files 2020-06-18 12:22:53 +03:00
Igor Chevdar
cf6eb138ce [box-tests] Turned on a test for JS_IR 2020-06-18 13:17:38 +05:00
Igor Chevdar
2bf73ccfe5 [IR] Supported extension receivers in SAM conversions 2020-06-18 13:17:38 +05:00
Ilya Muradyan
8c2baf0704 Add missing definitelyDoesNotContainName methods 2020-06-18 09:51:16 +02:00
Ilya Muradyan
573c60ed6b Add missing recordLookup implementations 2020-06-18 09:51:16 +02:00
Ilya Muradyan
7526ff9484 Compare lookups without respect to their order 2020-06-18 09:51:16 +02:00
Igor Chevdar
3634ad2d54 Added a test 2020-06-18 12:44:48 +05:00
Igor Chevdar
ecf9727568 [IR] Supported IrEnumEntry
Fixes https://youtrack.jetbrains.com/issue/KT-38996
2020-06-18 12:44:48 +05:00
461 changed files with 10164 additions and 4746 deletions

View File

@@ -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"
)
}
}

View File

@@ -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()
}
}

View File

@@ -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
}
}
}
}
}

View File

@@ -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)
})
}

View File

@@ -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

View File

@@ -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
))
}
}
}

View File

@@ -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 &&

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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.*

View File

@@ -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,

View File

@@ -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())
}
}

View File

@@ -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()

View File

@@ -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|

View File

@@ -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|
}

View File

@@ -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|

View File

@@ -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>>|

View File

@@ -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|
}

View File

@@ -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|

View File

@@ -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|

View File

@@ -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|
}

View File

@@ -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|
}

View File

@@ -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|

View File

@@ -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|

View File

@@ -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>|

View File

@@ -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|

View File

@@ -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>|

View File

@@ -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");

View File

@@ -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")

View File

@@ -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()
}
}

View File

@@ -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 ->

View File

@@ -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) }
}

View File

@@ -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")

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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()

View File

@@ -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) {

View File

@@ -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) }

View File

@@ -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()
}

View File

@@ -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))

View File

@@ -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)
}
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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() {
{

View File

@@ -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 {

View File

@@ -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? {

View File

@@ -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(

View File

@@ -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)

View File

@@ -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>

View File

@@ -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(

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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)) }
})
}
}

View File

@@ -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")

View File

@@ -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) {

View File

@@ -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)
}
}
}

View File

@@ -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)
}
}
}

View File

@@ -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"
}

View File

@@ -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() =

View File

@@ -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)
}

View File

@@ -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) {

View File

@@ -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)) {

View File

@@ -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,

View File

@@ -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,
)

View File

@@ -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

View File

@@ -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

View File

@@ -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 */ }
}
}

View File

@@ -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 = ""

View File

@@ -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"

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// KJS_WITH_FULL_RUNTIME
fun foo(): Array<Boolean> {

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// KJS_WITH_FULL_RUNTIME
fun foo(): Array<Boolean> {

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST

View File

@@ -0,0 +1,5 @@
enum class E(val b: Boolean) {
TRUE(1 == 1)
}
fun box() = if (E.TRUE.b) "OK" else "fail"

View File

@@ -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

View 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"

View File

@@ -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

View File

@@ -9,6 +9,7 @@ interface Z<T> {
}
}
@JvmDefaultWithoutCompatibility
open class ZImpl : Z<String>
class ZImpl2 : ZImpl() {

View File

@@ -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() {

View 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 }
}

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
// WITH_RUNTIME

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
// WITH_RUNTIME

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
// WITH_RUNTIME

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
// WITH_RUNTIME

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
// WITH_RUNTIME

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
// WITH_RUNTIME

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
// WITH_RUNTIME

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
// WITH_RUNTIME

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
// WITH_RUNTIME

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
fun inInt(x: Long): Boolean {

View File

@@ -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

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
fun box(): String {

View File

@@ -1,3 +1,4 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TODO: investigate should it be ran for JS or not
// TARGET_BACKEND: JVM

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT

View File

@@ -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