Move more common parts from :compiler:descriptors.jvm

This commit is contained in:
Dmitriy Novozhilov
2020-09-02 15:07:07 +03:00
parent 192e07a07b
commit 1417fcecb8
26 changed files with 235 additions and 205 deletions
@@ -0,0 +1,10 @@
/*
* 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.load.java
enum class AnnotationQualifierApplicabilityType {
METHOD_RETURN_TYPE, VALUE_PARAMETER, FIELD, TYPE_USE
}
@@ -0,0 +1,31 @@
/*
* 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.load.java
import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifier
import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifierWithMigrationStatus
import org.jetbrains.kotlin.name.FqName
val TYPE_QUALIFIER_NICKNAME_FQNAME = FqName("javax.annotation.meta.TypeQualifierNickname")
val TYPE_QUALIFIER_FQNAME = FqName("javax.annotation.meta.TypeQualifier")
val TYPE_QUALIFIER_DEFAULT_FQNAME = FqName("javax.annotation.meta.TypeQualifierDefault")
val MIGRATION_ANNOTATION_FQNAME = FqName("kotlin.annotations.jvm.UnderMigration")
val BUILT_IN_TYPE_QUALIFIER_DEFAULT_ANNOTATIONS = mapOf(
FqName("javax.annotation.ParametersAreNullableByDefault") to
NullabilityQualifierWithApplicability(
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE),
listOf(AnnotationQualifierApplicabilityType.VALUE_PARAMETER)
),
FqName("javax.annotation.ParametersAreNonnullByDefault") to
NullabilityQualifierWithApplicability(
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL),
listOf(AnnotationQualifierApplicabilityType.VALUE_PARAMETER)
)
)
val BUILT_IN_TYPE_QUALIFIER_FQ_NAMES = setOf(JAVAX_NONNULL_ANNOTATION, JAVAX_CHECKFORNULL_ANNOTATION)
@@ -0,0 +1,24 @@
/*
* 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.load.java
import org.jetbrains.kotlin.load.java.typeEnhancement.JavaTypeQualifiers
import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifierWithMigrationStatus
import java.util.*
typealias QualifierByApplicabilityType = EnumMap<AnnotationQualifierApplicabilityType, NullabilityQualifierWithMigrationStatus?>
class JavaTypeQualifiersByElementType(val nullabilityQualifiers: QualifierByApplicabilityType) {
operator fun get(applicabilityType: AnnotationQualifierApplicabilityType?): JavaTypeQualifiers? {
val nullabilityQualifierWithMigrationStatus = nullabilityQualifiers[applicabilityType] ?: return null
return JavaTypeQualifiers(
nullabilityQualifierWithMigrationStatus.qualifier, null,
isNotNullTypeParameter = false,
isNullabilityQualifierForWarning = nullabilityQualifierWithMigrationStatus.isForWarningOnly
)
}
}
@@ -0,0 +1,13 @@
/*
* 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.load.java
import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifierWithMigrationStatus
data class NullabilityQualifierWithApplicability(
val nullabilityQualifier: NullabilityQualifierWithMigrationStatus,
val qualifierApplicabilityTypes: Collection<AnnotationQualifierApplicabilityType>
)
@@ -0,0 +1,12 @@
/*
* 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.load.java.descriptors
sealed class AnnotationDefaultValue
class StringDefaultValue(val value: String) : AnnotationDefaultValue()
object NullDefaultValue : AnnotationDefaultValue()
@@ -0,0 +1,11 @@
/*
* 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.load.java.typeEnhancement
data class NullabilityQualifierWithMigrationStatus(
val qualifier: NullabilityQualifier,
val isForWarningOnly: Boolean = false
)
@@ -10,3 +10,5 @@ enum class TypeComponentPosition {
FLEXIBLE_UPPER,
INFLEXIBLE
}
fun TypeComponentPosition.shouldEnhance(): Boolean = this != TypeComponentPosition.INFLEXIBLE
@@ -0,0 +1,253 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.load.java.typeEnhancement
import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents
import org.jetbrains.kotlin.load.kotlin.signatures
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType.BOOLEAN
class TypeEnhancementInfo(val map: Map<Int, JavaTypeQualifiers>) {
constructor(vararg pairs: Pair<Int, JavaTypeQualifiers>) : this(mapOf(*pairs))
}
class PredefinedFunctionEnhancementInfo(
val returnTypeInfo: TypeEnhancementInfo? = null,
val parametersInfo: List<TypeEnhancementInfo?> = emptyList()
)
/** Type is always nullable: `T?` */
private val NULLABLE = JavaTypeQualifiers(NullabilityQualifier.NULLABLE, null, isNotNullTypeParameter = false)
/** Nullability depends on substitution, but the type is not platform: `T` */
private val NOT_PLATFORM = JavaTypeQualifiers(NullabilityQualifier.NOT_NULL, null, isNotNullTypeParameter = false)
/** Type is always non-nullable: `T & Any` */
private val NOT_NULLABLE = JavaTypeQualifiers(NullabilityQualifier.NOT_NULL, null, isNotNullTypeParameter = true)
@Suppress("LocalVariableName")
val PREDEFINED_FUNCTION_ENHANCEMENT_INFO_BY_SIGNATURE = signatures {
val JLObject = javaLang("Object")
val JFPredicate = javaFunction("Predicate")
val JFFunction = javaFunction("Function")
val JFConsumer = javaFunction("Consumer")
val JFBiFunction = javaFunction("BiFunction")
val JFBiConsumer = javaFunction("BiConsumer")
val JFUnaryOperator = javaFunction("UnaryOperator")
val JUStream = javaUtil("stream/Stream")
val JUOptional = javaUtil("Optional")
enhancement {
forClass(javaUtil("Iterator")) {
function("forEachRemaining") {
parameter(JFConsumer, NOT_PLATFORM, NOT_PLATFORM)
}
}
forClass(javaLang("Iterable")) {
function("spliterator") {
returns(javaUtil("Spliterator"), NOT_PLATFORM, NOT_PLATFORM)
}
}
forClass(javaUtil("Collection")) {
function("removeIf") {
parameter(JFPredicate, NOT_PLATFORM, NOT_PLATFORM)
returns(BOOLEAN)
}
function("stream") {
returns(JUStream, NOT_PLATFORM, NOT_PLATFORM)
}
function("parallelStream") {
returns(JUStream, NOT_PLATFORM, NOT_PLATFORM)
}
}
forClass(javaUtil("List")) {
function("replaceAll") {
parameter(JFUnaryOperator, NOT_PLATFORM, NOT_PLATFORM)
}
}
forClass(javaUtil("Map")) {
function("forEach") {
parameter(JFBiConsumer, NOT_PLATFORM, NOT_PLATFORM, NOT_PLATFORM)
}
function("putIfAbsent") {
parameter(JLObject, NOT_PLATFORM)
parameter(JLObject, NOT_PLATFORM)
returns(JLObject, NULLABLE)
}
function("replace") {
parameter(JLObject, NOT_PLATFORM)
parameter(JLObject, NOT_PLATFORM)
returns(JLObject, NULLABLE)
}
function("replace") {
parameter(JLObject, NOT_PLATFORM)
parameter(JLObject, NOT_PLATFORM)
parameter(JLObject, NOT_PLATFORM)
returns(BOOLEAN)
}
function("replaceAll") {
parameter(JFBiFunction, NOT_PLATFORM, NOT_PLATFORM, NOT_PLATFORM, NOT_PLATFORM)
}
function("compute") {
parameter(JLObject, NOT_PLATFORM)
parameter(JFBiFunction, NOT_PLATFORM, NOT_PLATFORM, NULLABLE, NULLABLE)
returns(JLObject, NULLABLE)
}
// while it is possible to return nullable value from lambda in computeIfAbsent,
// we deliberately make it just NOT_PLATFORM V in order to have the return type V and not V?
function("computeIfAbsent") {
parameter(JLObject, NOT_PLATFORM)
parameter(JFFunction, NOT_PLATFORM, NOT_PLATFORM, NOT_PLATFORM)
returns(JLObject, NOT_PLATFORM)
}
function("computeIfPresent") {
parameter(JLObject, NOT_PLATFORM)
parameter(JFBiFunction, NOT_PLATFORM, NOT_PLATFORM, NOT_NULLABLE, NULLABLE)
returns(JLObject, NULLABLE)
}
function("merge") {
parameter(JLObject, NOT_PLATFORM)
parameter(JLObject, NOT_NULLABLE)
parameter(JFBiFunction, NOT_PLATFORM, NOT_NULLABLE, NOT_NULLABLE, NULLABLE)
returns(JLObject, NULLABLE)
}
}
forClass(JUOptional) {
function("empty") {
returns(JUOptional, NOT_PLATFORM, NOT_NULLABLE)
}
function("of") {
parameter(JLObject, NOT_NULLABLE)
returns(JUOptional, NOT_PLATFORM, NOT_NULLABLE)
}
function("ofNullable") {
parameter(JLObject, NULLABLE)
returns(JUOptional, NOT_PLATFORM, NOT_NULLABLE)
}
function("get") {
returns(JLObject, NOT_NULLABLE)
}
function("ifPresent") {
parameter(JFConsumer, NOT_PLATFORM, NOT_NULLABLE)
}
}
forClass(javaLang("ref/Reference")) {
function("get") {
returns(JLObject, NULLABLE)
}
}
forClass(JFPredicate) {
function("test") {
parameter(JLObject, NOT_PLATFORM)
returns(BOOLEAN)
}
}
forClass(javaFunction("BiPredicate")) {
function("test") {
parameter(JLObject, NOT_PLATFORM)
parameter(JLObject, NOT_PLATFORM)
returns(BOOLEAN)
}
}
forClass(JFConsumer) {
function("accept") {
parameter(JLObject, NOT_PLATFORM)
}
}
forClass(JFBiConsumer) {
function("accept") {
parameter(JLObject, NOT_PLATFORM)
parameter(JLObject, NOT_PLATFORM)
}
}
forClass(JFFunction) {
function("apply") {
parameter(JLObject, NOT_PLATFORM)
returns(JLObject, NOT_PLATFORM)
}
}
forClass(JFBiFunction) {
function("apply") {
parameter(JLObject, NOT_PLATFORM)
parameter(JLObject, NOT_PLATFORM)
returns(JLObject, NOT_PLATFORM)
}
}
forClass(javaFunction("Supplier")) {
function("get") {
returns(JLObject, NOT_PLATFORM)
}
}
}
}
private inline fun enhancement(block: SignatureEnhancementBuilder.() -> Unit): Map<String, PredefinedFunctionEnhancementInfo> =
SignatureEnhancementBuilder().apply(block).build()
private class SignatureEnhancementBuilder {
private val signatures = mutableMapOf<String, PredefinedFunctionEnhancementInfo>()
inline fun forClass(internalName: String, block: ClassEnhancementBuilder.() -> Unit) =
ClassEnhancementBuilder(internalName).block()
inner class ClassEnhancementBuilder(val className: String) {
fun function(name: String, block: FunctionEnhancementBuilder.() -> Unit) {
signatures += FunctionEnhancementBuilder(name).apply(block).build()
}
inner class FunctionEnhancementBuilder(val functionName: String) {
private val parameters = mutableListOf<Pair<String, TypeEnhancementInfo?>>()
private var returnType: Pair<String, TypeEnhancementInfo?> = "V" to null
fun parameter(type: String, vararg pairs: Pair<Int, JavaTypeQualifiers>) {
parameters += type to
if (pairs.isEmpty()) null else TypeEnhancementInfo(*pairs)
}
fun parameter(type: String, vararg qualifiers: JavaTypeQualifiers) {
parameters += type to
if (qualifiers.isEmpty()) null else TypeEnhancementInfo(
qualifiers.withIndex().associateBy(
{ it.index },
{ it.value })
)
}
fun returns(type: String, vararg pairs: Pair<Int, JavaTypeQualifiers>) {
returnType = type to TypeEnhancementInfo(*pairs)
}
fun returns(type: String, vararg qualifiers: JavaTypeQualifiers) {
returnType = type to TypeEnhancementInfo(qualifiers.withIndex().associateBy({ it.index }, { it.value }))
}
fun returns(type: JvmPrimitiveType) {
returnType = type.desc to null
}
fun build() = with(SignatureBuildingComponents) {
signature(className, jvmDescriptor(functionName, parameters.map { it.first }, returnType.first)) to
PredefinedFunctionEnhancementInfo(returnType.second, parameters.map { it.second })
}
}
}
fun build(): Map<String, PredefinedFunctionEnhancementInfo> = signatures
}
@@ -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.load.java.typeEnhancement
fun createJavaTypeQualifiers(
nullability: NullabilityQualifier?,
mutability: MutabilityQualifier?,
forWarning: Boolean,
isAnyNonNullTypeParameter: Boolean
): JavaTypeQualifiers {
if (!isAnyNonNullTypeParameter || nullability != NullabilityQualifier.NOT_NULL) {
return JavaTypeQualifiers(nullability, mutability, false, forWarning)
}
return JavaTypeQualifiers(nullability, mutability, true, forWarning)
}
fun <T : Any> Set<T>.select(low: T, high: T, own: T?, isCovariant: Boolean): T? {
if (isCovariant) {
val supertypeQualifier = if (low in this) low else if (high in this) high else null
return if (supertypeQualifier == low && own == high) null else own ?: supertypeQualifier
}
// isInvariant
val effectiveSet = own?.let { (this + own).toSet() } ?: this
// if this set contains exactly one element, it is the qualifier everybody agrees upon,
// otherwise (no qualifiers, or multiple qualifiers), there's no single such qualifier
// and all qualifiers are discarded
return effectiveSet.singleOrNull()
}
fun Set<NullabilityQualifier>.select(own: NullabilityQualifier?, isCovariant: Boolean) =
if (own == NullabilityQualifier.FORCE_FLEXIBILITY)
NullabilityQualifier.FORCE_FLEXIBILITY
else
select(NullabilityQualifier.NOT_NULL, NullabilityQualifier.NULLABLE, own, isCovariant)
@@ -0,0 +1,28 @@
/*
* 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.load.java.typeEnhancement
enum class NullabilityQualifier {
NULLABLE,
NOT_NULL,
FORCE_FLEXIBILITY
}
enum class MutabilityQualifier {
READ_ONLY,
MUTABLE
}
class JavaTypeQualifiers(
val nullability: NullabilityQualifier?,
val mutability: MutabilityQualifier?,
val isNotNullTypeParameter: Boolean,
val isNullabilityQualifierForWarning: Boolean = false
) {
companion object {
val NONE = JavaTypeQualifiers(null, null, false)
}
}
@@ -0,0 +1,32 @@
/*
* 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.load.kotlin
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.serialization.deserialization.ClassData
interface PackagePartProvider {
/**
* @return JVM internal names of package parts existing in the package with the given FQ name.
*
* For example, if a file named foo.kt in package org.test is compiled to a library, PackagePartProvider for such library
* must return the list `["org/test/FooKt"]` for the query `"org.test"`
* (in case the file is not annotated with @JvmName, @JvmPackageName or @JvmMultifileClass).
*/
fun findPackageParts(packageFqName: String): List<String>
fun getAnnotationsOnBinaryModule(moduleName: String): List<ClassId>
fun getAllOptionalAnnotationClasses(): List<ClassData>
object Empty : PackagePartProvider {
override fun findPackageParts(packageFqName: String): List<String> = emptyList()
override fun getAnnotationsOnBinaryModule(moduleName: String): List<ClassId> = emptyList()
override fun getAllOptionalAnnotationClasses(): List<ClassData> = emptyList()
}
}