Rename :core:descriptors.common to :core:compiler.common
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
jvmTarget = "1.6"
|
||||
javaHome = rootProject.extra["JDK_16"] as String
|
||||
|
||||
dependencies {
|
||||
compile(project(":core:util.runtime"))
|
||||
compile(kotlinStdlib())
|
||||
compile(project(":kotlin-annotations-jvm"))
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" {}
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile> {
|
||||
sourceCompatibility = "1.6"
|
||||
targetCompatibility = "1.6"
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.builtins
|
||||
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
enum class PrimitiveType(typeName: String) {
|
||||
BOOLEAN("Boolean"),
|
||||
CHAR("Char"),
|
||||
BYTE("Byte"),
|
||||
SHORT("Short"),
|
||||
INT("Int"),
|
||||
FLOAT("Float"),
|
||||
LONG("Long"),
|
||||
DOUBLE("Double"),
|
||||
;
|
||||
|
||||
val typeName: Name = Name.identifier(typeName)
|
||||
|
||||
val arrayTypeName: Name = Name.identifier("${typeName}Array")
|
||||
|
||||
val typeFqName: FqName by lazy(LazyThreadSafetyMode.PUBLICATION) { StandardNames.BUILT_INS_PACKAGE_FQ_NAME.child(this.typeName) }
|
||||
|
||||
val arrayTypeFqName: FqName by lazy(LazyThreadSafetyMode.PUBLICATION) { StandardNames.BUILT_INS_PACKAGE_FQ_NAME.child(arrayTypeName) }
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val NUMBER_TYPES = setOf(CHAR, BYTE, SHORT, INT, FLOAT, LONG, DOUBLE)
|
||||
|
||||
@JvmStatic
|
||||
fun getByShortName(name: String): PrimitiveType? = when (name) {
|
||||
"Boolean" -> BOOLEAN
|
||||
"Char" -> CHAR
|
||||
"Byte" -> BYTE
|
||||
"Short" -> SHORT
|
||||
"Int" -> INT
|
||||
"Float" -> FLOAT
|
||||
"Long" -> LONG
|
||||
"Double" -> DOUBLE
|
||||
else -> null
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getByShortArrayName(name: String): PrimitiveType? = when (name) {
|
||||
"BooleanArray" -> BOOLEAN
|
||||
"CharArray" -> CHAR
|
||||
"ByteArray" -> BYTE
|
||||
"ShortArray" -> SHORT
|
||||
"IntArray" -> INT
|
||||
"FloatArray" -> FLOAT
|
||||
"LongArray" -> LONG
|
||||
"DoubleArray" -> DOUBLE
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* 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.builtins
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames.FqNames.reflect
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.newHashMapWithExpectedSize
|
||||
import org.jetbrains.kotlin.utils.newHashSetWithExpectedSize
|
||||
|
||||
@Suppress("Reformat")
|
||||
object StandardNames {
|
||||
@JvmField val ENUM_VALUES = Name.identifier("values")
|
||||
|
||||
@JvmField val ENUM_VALUE_OF = Name.identifier("valueOf")
|
||||
|
||||
@JvmField val COROUTINES_PACKAGE_FQ_NAME_RELEASE = FqName("kotlin.coroutines")
|
||||
|
||||
@JvmField val COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL = COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier("experimental"))
|
||||
|
||||
@JvmField val COROUTINES_INTRINSICS_PACKAGE_FQ_NAME_EXPERIMENTAL = COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("intrinsics"))
|
||||
|
||||
@JvmField val CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL = COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("Continuation"))
|
||||
|
||||
@JvmField val CONTINUATION_INTERFACE_FQ_NAME_RELEASE = COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier("Continuation"))
|
||||
|
||||
@JvmField val RESULT_FQ_NAME = FqName("kotlin.Result")
|
||||
|
||||
@JvmField val KOTLIN_REFLECT_FQ_NAME = FqName("kotlin.reflect")
|
||||
const val K_PROPERTY_PREFIX = "KProperty"
|
||||
const val K_MUTABLE_PROPERTY_PREFIX = "KMutableProperty"
|
||||
const val K_FUNCTION_PREFIX = "KFunction"
|
||||
const val K_SUSPEND_FUNCTION_PREFIX = "KSuspendFunction"
|
||||
|
||||
@JvmField val PREFIXES = listOf(K_PROPERTY_PREFIX, K_MUTABLE_PROPERTY_PREFIX, K_FUNCTION_PREFIX, K_SUSPEND_FUNCTION_PREFIX)
|
||||
|
||||
@JvmField
|
||||
val BUILT_INS_PACKAGE_NAME = Name.identifier("kotlin")
|
||||
|
||||
@JvmField
|
||||
val BUILT_INS_PACKAGE_FQ_NAME = FqName.topLevel(BUILT_INS_PACKAGE_NAME)
|
||||
|
||||
@JvmField
|
||||
val ANNOTATION_PACKAGE_FQ_NAME = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("annotation"))
|
||||
|
||||
@JvmField
|
||||
val COLLECTIONS_PACKAGE_FQ_NAME = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("collections"))
|
||||
|
||||
@JvmField
|
||||
val RANGES_PACKAGE_FQ_NAME = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("ranges"))
|
||||
|
||||
@JvmField
|
||||
val TEXT_PACKAGE_FQ_NAME = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("text"))
|
||||
|
||||
@JvmField
|
||||
val BUILT_INS_PACKAGE_FQ_NAMES = setOf(
|
||||
BUILT_INS_PACKAGE_FQ_NAME,
|
||||
COLLECTIONS_PACKAGE_FQ_NAME,
|
||||
RANGES_PACKAGE_FQ_NAME,
|
||||
ANNOTATION_PACKAGE_FQ_NAME,
|
||||
KOTLIN_REFLECT_FQ_NAME,
|
||||
BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("internal")),
|
||||
COROUTINES_PACKAGE_FQ_NAME_RELEASE
|
||||
)
|
||||
|
||||
object FqNames {
|
||||
@JvmField val any: FqNameUnsafe = fqNameUnsafe("Any")
|
||||
@JvmField val nothing: FqNameUnsafe = fqNameUnsafe("Nothing")
|
||||
@JvmField val cloneable: FqNameUnsafe = fqNameUnsafe("Cloneable")
|
||||
@JvmField val suppress: FqName = fqName("Suppress")
|
||||
@JvmField val unit: FqNameUnsafe = fqNameUnsafe("Unit")
|
||||
@JvmField val charSequence: FqNameUnsafe = fqNameUnsafe("CharSequence")
|
||||
@JvmField val string: FqNameUnsafe = fqNameUnsafe("String")
|
||||
@JvmField val array: FqNameUnsafe = fqNameUnsafe("Array")
|
||||
|
||||
@JvmField val _boolean: FqNameUnsafe = fqNameUnsafe("Boolean")
|
||||
@JvmField val _char: FqNameUnsafe = fqNameUnsafe("Char")
|
||||
@JvmField val _byte: FqNameUnsafe = fqNameUnsafe("Byte")
|
||||
@JvmField val _short: FqNameUnsafe = fqNameUnsafe("Short")
|
||||
@JvmField val _int: FqNameUnsafe = fqNameUnsafe("Int")
|
||||
@JvmField val _long: FqNameUnsafe = fqNameUnsafe("Long")
|
||||
@JvmField val _float: FqNameUnsafe = fqNameUnsafe("Float")
|
||||
@JvmField val _double: FqNameUnsafe = fqNameUnsafe("Double")
|
||||
@JvmField val number: FqNameUnsafe = fqNameUnsafe("Number")
|
||||
|
||||
@JvmField val _enum: FqNameUnsafe = fqNameUnsafe("Enum")
|
||||
|
||||
@JvmField val functionSupertype: FqNameUnsafe = fqNameUnsafe("Function")
|
||||
|
||||
@JvmField val throwable: FqName = fqName("Throwable")
|
||||
@JvmField val comparable: FqName = fqName("Comparable")
|
||||
|
||||
@JvmField val intRange: FqNameUnsafe = rangesFqName("IntRange")
|
||||
@JvmField val longRange: FqNameUnsafe = rangesFqName("LongRange")
|
||||
|
||||
@JvmField val deprecated: FqName = fqName("Deprecated")
|
||||
@JvmField val deprecatedSinceKotlin: FqName = fqName("DeprecatedSinceKotlin")
|
||||
@JvmField val deprecationLevel: FqName = fqName("DeprecationLevel")
|
||||
@JvmField val replaceWith: FqName = fqName("ReplaceWith")
|
||||
@JvmField val extensionFunctionType: FqName = fqName("ExtensionFunctionType")
|
||||
@JvmField val parameterName: FqName = fqName("ParameterName")
|
||||
@JvmField val annotation: FqName = fqName("Annotation")
|
||||
@JvmField val target: FqName = annotationName("Target")
|
||||
@JvmField val annotationTarget: FqName = annotationName("AnnotationTarget")
|
||||
@JvmField val annotationRetention: FqName = annotationName("AnnotationRetention")
|
||||
@JvmField val retention: FqName = annotationName("Retention")
|
||||
@JvmField val repeatable: FqName = annotationName("Repeatable")
|
||||
@JvmField val mustBeDocumented: FqName = annotationName("MustBeDocumented")
|
||||
@JvmField val unsafeVariance: FqName = fqName("UnsafeVariance")
|
||||
@JvmField val publishedApi: FqName = fqName("PublishedApi")
|
||||
|
||||
@JvmField val iterator: FqName = collectionsFqName("Iterator")
|
||||
@JvmField val iterable: FqName = collectionsFqName("Iterable")
|
||||
@JvmField val collection: FqName = collectionsFqName("Collection")
|
||||
@JvmField val list: FqName = collectionsFqName("List")
|
||||
@JvmField val listIterator: FqName = collectionsFqName("ListIterator")
|
||||
@JvmField val set: FqName = collectionsFqName("Set")
|
||||
@JvmField val map: FqName = collectionsFqName("Map")
|
||||
@JvmField val mapEntry: FqName = map.child(Name.identifier("Entry"))
|
||||
@JvmField val mutableIterator: FqName = collectionsFqName("MutableIterator")
|
||||
@JvmField val mutableIterable: FqName = collectionsFqName("MutableIterable")
|
||||
@JvmField val mutableCollection: FqName = collectionsFqName("MutableCollection")
|
||||
@JvmField val mutableList: FqName = collectionsFqName("MutableList")
|
||||
@JvmField val mutableListIterator: FqName = collectionsFqName("MutableListIterator")
|
||||
@JvmField val mutableSet: FqName = collectionsFqName("MutableSet")
|
||||
@JvmField val mutableMap: FqName = collectionsFqName("MutableMap")
|
||||
@JvmField val mutableMapEntry: FqName = mutableMap.child(Name.identifier("MutableEntry"))
|
||||
|
||||
@JvmField val kClass: FqNameUnsafe = reflect("KClass")
|
||||
@JvmField val kCallable: FqNameUnsafe = reflect("KCallable")
|
||||
@JvmField val kProperty0: FqNameUnsafe = reflect("KProperty0")
|
||||
@JvmField val kProperty1: FqNameUnsafe = reflect("KProperty1")
|
||||
@JvmField val kProperty2: FqNameUnsafe = reflect("KProperty2")
|
||||
@JvmField val kMutableProperty0: FqNameUnsafe = reflect("KMutableProperty0")
|
||||
@JvmField val kMutableProperty1: FqNameUnsafe = reflect("KMutableProperty1")
|
||||
@JvmField val kMutableProperty2: FqNameUnsafe = reflect("KMutableProperty2")
|
||||
@JvmField val kPropertyFqName: FqNameUnsafe = reflect("KProperty")
|
||||
@JvmField val kMutablePropertyFqName: FqNameUnsafe = reflect("KMutableProperty")
|
||||
@JvmField val kProperty: ClassId = ClassId.topLevel(kPropertyFqName.toSafe())
|
||||
@JvmField val kDeclarationContainer: FqNameUnsafe = reflect("KDeclarationContainer")
|
||||
|
||||
@JvmField val uByteFqName: FqName = fqName("UByte")
|
||||
@JvmField val uShortFqName: FqName = fqName("UShort")
|
||||
@JvmField val uIntFqName: FqName = fqName("UInt")
|
||||
@JvmField val uLongFqName: FqName = fqName("ULong")
|
||||
@JvmField val uByte: ClassId = ClassId.topLevel(uByteFqName)
|
||||
@JvmField val uShort: ClassId = ClassId.topLevel(uShortFqName)
|
||||
@JvmField val uInt: ClassId = ClassId.topLevel(uIntFqName)
|
||||
@JvmField val uLong: ClassId = ClassId.topLevel(uLongFqName)
|
||||
|
||||
@JvmField val primitiveTypeShortNames: Set<Name> = newHashSetWithExpectedSize<Name>(PrimitiveType.values().size).apply {
|
||||
PrimitiveType.values().mapTo(this) { it.typeName }
|
||||
}
|
||||
|
||||
@JvmField val primitiveArrayTypeShortNames: Set<Name> = newHashSetWithExpectedSize<Name>(PrimitiveType.values().size).apply {
|
||||
PrimitiveType.values().mapTo(this) { it.arrayTypeName }
|
||||
}
|
||||
|
||||
@JvmField val fqNameToPrimitiveType: Map<FqNameUnsafe, PrimitiveType> =
|
||||
newHashMapWithExpectedSize<FqNameUnsafe, PrimitiveType>(PrimitiveType.values().size).apply {
|
||||
for (primitiveType in PrimitiveType.values()) {
|
||||
this[fqNameUnsafe(primitiveType.typeName.asString())] = primitiveType
|
||||
}
|
||||
}
|
||||
|
||||
@JvmField val arrayClassFqNameToPrimitiveType: MutableMap<FqNameUnsafe, PrimitiveType> =
|
||||
newHashMapWithExpectedSize<FqNameUnsafe, PrimitiveType>(PrimitiveType.values().size).apply {
|
||||
for (primitiveType in PrimitiveType.values()) {
|
||||
this[fqNameUnsafe(primitiveType.arrayTypeName.asString())] = primitiveType
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun fqNameUnsafe(simpleName: String): FqNameUnsafe {
|
||||
return fqName(simpleName).toUnsafe()
|
||||
}
|
||||
|
||||
private fun fqName(simpleName: String): FqName {
|
||||
return BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(simpleName))
|
||||
}
|
||||
|
||||
private fun collectionsFqName(simpleName: String): FqName {
|
||||
return COLLECTIONS_PACKAGE_FQ_NAME.child(Name.identifier(simpleName))
|
||||
}
|
||||
|
||||
private fun rangesFqName(simpleName: String): FqNameUnsafe {
|
||||
return RANGES_PACKAGE_FQ_NAME.child(Name.identifier(simpleName)).toUnsafe()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun reflect(simpleName: String): FqNameUnsafe {
|
||||
return KOTLIN_REFLECT_FQ_NAME.child(Name.identifier(simpleName)).toUnsafe()
|
||||
}
|
||||
|
||||
private fun annotationName(simpleName: String): FqName {
|
||||
return ANNOTATION_PACKAGE_FQ_NAME.child(Name.identifier(simpleName))
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getFunctionName(parameterCount: Int): String {
|
||||
return "Function$parameterCount"
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getKFunctionFqName(parameterCount: Int): FqNameUnsafe {
|
||||
return reflect(FunctionClassKind.KFunction.classNamePrefix + parameterCount)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getFunctionClassId(parameterCount: Int): ClassId {
|
||||
return ClassId(BUILT_INS_PACKAGE_FQ_NAME, Name.identifier(getFunctionName(parameterCount)))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getSuspendFunctionName(parameterCount: Int): String {
|
||||
return FunctionClassKind.SuspendFunction.classNamePrefix + parameterCount
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getSuspendFunctionClassId(parameterCount: Int): ClassId {
|
||||
return ClassId(COROUTINES_PACKAGE_FQ_NAME_RELEASE, Name.identifier(getSuspendFunctionName(parameterCount)))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isPrimitiveArray(arrayFqName: FqNameUnsafe): Boolean {
|
||||
return FqNames.arrayClassFqNameToPrimitiveType.get(arrayFqName) != null
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getPrimitiveFqName(primitiveType: PrimitiveType): FqName {
|
||||
return BUILT_INS_PACKAGE_FQ_NAME.child(primitiveType.typeName)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.builtins.functions
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
enum class FunctionClassKind(val packageFqName: FqName, val classNamePrefix: String) {
|
||||
Function(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Function"),
|
||||
SuspendFunction(StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE, "SuspendFunction"),
|
||||
KFunction(StandardNames.KOTLIN_REFLECT_FQ_NAME, "KFunction"),
|
||||
KSuspendFunction(StandardNames.KOTLIN_REFLECT_FQ_NAME, "KSuspendFunction");
|
||||
|
||||
fun numberedClassName(arity: Int) = Name.identifier("$classNamePrefix$arity")
|
||||
|
||||
companion object {
|
||||
fun byClassNamePrefix(packageFqName: FqName, className: String): FunctionClassKind? =
|
||||
values().firstOrNull { it.packageFqName == packageFqName && className.startsWith(it.classNamePrefix) }
|
||||
|
||||
data class KindWithArity(val kind: FunctionClassKind, val arity: Int)
|
||||
|
||||
fun parseClassName(className: String, packageFqName: FqName): KindWithArity? {
|
||||
val kind = byClassNamePrefix(packageFqName, className) ?: return null
|
||||
|
||||
val prefix = kind.classNamePrefix
|
||||
|
||||
val arity = toInt(className.substring(prefix.length)) ?: return null
|
||||
|
||||
// TODO: validate arity, should be <= 255
|
||||
return KindWithArity(kind, arity)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getFunctionalClassKind(className: String, packageFqName: FqName) =
|
||||
parseClassName(className, packageFqName)?.kind
|
||||
|
||||
private fun toInt(s: String): Int? {
|
||||
if (s.isEmpty()) return null
|
||||
|
||||
var result = 0
|
||||
for (c in s) {
|
||||
val d = c - '0'
|
||||
if (d !in 0..9) return null
|
||||
result = result * 10 + d
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.contracts.description
|
||||
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
enum class EventOccurrencesRange(private val left: Int, private val right: Int) {
|
||||
ZERO(0, 0), // 0..0
|
||||
AT_MOST_ONCE(0, 1), // 0..1
|
||||
EXACTLY_ONCE(1, 1), // 1..1
|
||||
AT_LEAST_ONCE(1, 3), // 1..*
|
||||
MORE_THAN_ONCE(2, 3), // 2..*
|
||||
UNKNOWN(0, 3); // 0..*
|
||||
|
||||
companion object {
|
||||
private fun fromRange(left: Int, right: Int): EventOccurrencesRange = when (min(left, 2) to min(right, 3)) {
|
||||
0 to 0 -> ZERO
|
||||
0 to 1 -> AT_MOST_ONCE
|
||||
0 to 2 -> UNKNOWN
|
||||
0 to 3 -> UNKNOWN
|
||||
1 to 1 -> EXACTLY_ONCE
|
||||
1 to 2 -> AT_LEAST_ONCE
|
||||
1 to 3 -> AT_LEAST_ONCE
|
||||
2 to 2 -> MORE_THAN_ONCE
|
||||
2 to 3 -> MORE_THAN_ONCE
|
||||
3 to 3 -> MORE_THAN_ONCE
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
|
||||
fun or(x: EventOccurrencesRange, y: EventOccurrencesRange): EventOccurrencesRange =
|
||||
fromRange(min(x.left, y.left), max(x.right, y.right))
|
||||
|
||||
fun plus(x: EventOccurrencesRange, y: EventOccurrencesRange): EventOccurrencesRange =
|
||||
fromRange(x.left + y.left, x.right + y.right)
|
||||
}
|
||||
|
||||
infix fun or(other: EventOccurrencesRange): EventOccurrencesRange = Companion.or(this, other)
|
||||
operator fun plus(other: EventOccurrencesRange): EventOccurrencesRange = Companion.plus(this, other)
|
||||
operator fun contains(other: EventOccurrencesRange): Boolean = left <= other.left && other.right <= right
|
||||
}
|
||||
|
||||
fun EventOccurrencesRange.isDefinitelyVisited(): Boolean =
|
||||
this == EventOccurrencesRange.EXACTLY_ONCE || this == EventOccurrencesRange.AT_LEAST_ONCE || this == EventOccurrencesRange.MORE_THAN_ONCE
|
||||
|
||||
fun EventOccurrencesRange.canBeRevisited(): Boolean =
|
||||
this == EventOccurrencesRange.UNKNOWN || this == EventOccurrencesRange.AT_LEAST_ONCE || this == EventOccurrencesRange.MORE_THAN_ONCE
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors;
|
||||
|
||||
public enum ClassKind {
|
||||
CLASS,
|
||||
INTERFACE,
|
||||
ENUM_CLASS,
|
||||
ENUM_ENTRY,
|
||||
ANNOTATION_CLASS,
|
||||
OBJECT;
|
||||
|
||||
public boolean isSingleton() {
|
||||
return this == OBJECT || this == ENUM_ENTRY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.descriptors
|
||||
|
||||
// For sealed classes, isOverridable is false but isOverridableByMembers is true
|
||||
enum class Modality {
|
||||
// THE ORDER OF ENTRIES MATTERS HERE
|
||||
FINAL,
|
||||
// NB: class can be sealed but not function or property
|
||||
SEALED,
|
||||
OPEN,
|
||||
ABSTRACT;
|
||||
|
||||
companion object {
|
||||
|
||||
// NB: never returns SEALED
|
||||
fun convertFromFlags(abstract: Boolean, open: Boolean): Modality {
|
||||
if (abstract) return ABSTRACT
|
||||
if (open) return OPEN
|
||||
return FINAL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.descriptors
|
||||
|
||||
class ModuleCapability<T>(val name: String) {
|
||||
override fun toString() = name
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface SourceElement {
|
||||
SourceElement NO_SOURCE = new SourceElement() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NO_SOURCE";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SourceFile getContainingFile() {
|
||||
return SourceFile.NO_SOURCE_FILE;
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
SourceFile getContainingFile();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface SourceFile {
|
||||
SourceFile NO_SOURCE_FILE = new SourceFile() {
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable
|
||||
String getName();
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.annotations
|
||||
|
||||
enum class AnnotationUseSiteTarget(renderName: String? = null) {
|
||||
FIELD(),
|
||||
FILE(),
|
||||
PROPERTY(),
|
||||
PROPERTY_GETTER("get"),
|
||||
PROPERTY_SETTER("set"),
|
||||
RECEIVER(),
|
||||
CONSTRUCTOR_PARAMETER("param"),
|
||||
SETTER_PARAMETER("setparam"),
|
||||
PROPERTY_DELEGATE_FIELD("delegate");
|
||||
|
||||
val renderName: String = renderName ?: name.toLowerCase()
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.incremental.components
|
||||
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation
|
||||
import java.io.File
|
||||
|
||||
@DefaultImplementation(ExpectActualTracker.DoNothing::class)
|
||||
interface ExpectActualTracker {
|
||||
fun report(expectedFile: File, actualFile: File)
|
||||
|
||||
object DoNothing : ExpectActualTracker {
|
||||
override fun report(expectedFile: File, actualFile: File) {
|
||||
}
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental.components
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
interface LookupLocation {
|
||||
val location: LocationInfo?
|
||||
}
|
||||
|
||||
interface LocationInfo {
|
||||
val filePath: String
|
||||
|
||||
// only for tests
|
||||
val position: Position
|
||||
}
|
||||
|
||||
data class Position(val line: Int, val column: Int) : Serializable {
|
||||
companion object {
|
||||
val NO_POSITION = Position(-1, -1)
|
||||
}
|
||||
}
|
||||
|
||||
enum class NoLookupLocation : LookupLocation {
|
||||
FROM_IDE,
|
||||
FROM_BACKEND,
|
||||
FROM_TEST,
|
||||
FROM_BUILTINS,
|
||||
WHEN_CHECK_DECLARATION_CONFLICTS,
|
||||
WHEN_CHECK_OVERRIDES,
|
||||
FOR_SCRIPT,
|
||||
FROM_REFLECTION,
|
||||
WHEN_RESOLVE_DECLARATION,
|
||||
WHEN_GET_DECLARATION_SCOPE,
|
||||
WHEN_RESOLVING_DEFAULT_TYPE_ARGUMENTS,
|
||||
FOR_ALREADY_TRACKED,
|
||||
// TODO replace with real location (e.g. FROM_IDE) where it possible
|
||||
WHEN_GET_ALL_DESCRIPTORS,
|
||||
WHEN_TYPING,
|
||||
WHEN_GET_SUPER_MEMBERS,
|
||||
FOR_NON_TRACKED_SCOPE,
|
||||
FROM_SYNTHETIC_SCOPE,
|
||||
FROM_DESERIALIZATION,
|
||||
FROM_JAVA_LOADER,
|
||||
WHEN_GET_LOCAL_VARIABLE,
|
||||
WHEN_FIND_BY_FQNAME,
|
||||
WHEN_GET_COMPANION_OBJECT,
|
||||
FOR_DEFAULT_IMPORTS;
|
||||
|
||||
override val location: LocationInfo? get() = null
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.incremental.components
|
||||
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation
|
||||
import java.io.Serializable
|
||||
|
||||
@DefaultImplementation(LookupTracker.DO_NOTHING::class)
|
||||
interface LookupTracker {
|
||||
// used in tests for more accurate checks
|
||||
val requiresPosition: Boolean
|
||||
|
||||
fun record(
|
||||
filePath: String,
|
||||
position: Position,
|
||||
scopeFqName: String,
|
||||
scopeKind: ScopeKind,
|
||||
name: String
|
||||
)
|
||||
|
||||
object DO_NOTHING : LookupTracker {
|
||||
override val requiresPosition: Boolean
|
||||
get() = false
|
||||
|
||||
override fun record(filePath: String, position: Position, scopeFqName: String, scopeKind: ScopeKind, name: String) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class ScopeKind {
|
||||
PACKAGE,
|
||||
CLASSIFIER
|
||||
}
|
||||
|
||||
data class LookupInfo(
|
||||
val filePath: String,
|
||||
val position: Position,
|
||||
val scopeFqName: String,
|
||||
val scopeKind: ScopeKind,
|
||||
val name: String
|
||||
) : Serializable
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.name;
|
||||
|
||||
import kotlin.text.StringsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* A class name which is used to uniquely identify a Kotlin class.
|
||||
*
|
||||
* If local = true, the class represented by this id is either itself local or is an inner class of some local class. This also means that
|
||||
* the first non-class container of the class is not a package.
|
||||
* In the case of a local class, relativeClassName consists of a single name including all callables' and class' names all the way up to
|
||||
* the package, separated by dollar signs. If a class is an inner of local, relativeClassName would consist of two names,
|
||||
* the second one being the class' short name.
|
||||
*/
|
||||
public final class ClassId {
|
||||
@NotNull
|
||||
public static ClassId topLevel(@NotNull FqName topLevelFqName) {
|
||||
return new ClassId(topLevelFqName.parent(), topLevelFqName.shortName());
|
||||
}
|
||||
|
||||
private final FqName packageFqName;
|
||||
private final FqName relativeClassName;
|
||||
private final boolean local;
|
||||
|
||||
public ClassId(@NotNull FqName packageFqName, @NotNull FqName relativeClassName, boolean local) {
|
||||
this.packageFqName = packageFqName;
|
||||
assert !relativeClassName.isRoot() :
|
||||
"Class name must not be root: " + packageFqName + (local ? " (local)" : "");
|
||||
this.relativeClassName = relativeClassName;
|
||||
this.local = local;
|
||||
}
|
||||
|
||||
public ClassId(@NotNull FqName packageFqName, @NotNull Name topLevelName) {
|
||||
this(packageFqName, FqName.topLevel(topLevelName), false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FqName getPackageFqName() {
|
||||
return packageFqName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FqName getRelativeClassName() {
|
||||
return relativeClassName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Name getShortClassName() {
|
||||
return relativeClassName.shortName();
|
||||
}
|
||||
|
||||
public boolean isLocal() {
|
||||
return local;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClassId createNestedClassId(@NotNull Name name) {
|
||||
return new ClassId(getPackageFqName(), relativeClassName.child(name), local);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ClassId getOuterClassId() {
|
||||
FqName parent = relativeClassName.parent();
|
||||
return parent.isRoot() ? null : new ClassId(getPackageFqName(), parent, local);
|
||||
}
|
||||
|
||||
public boolean isNestedClass() {
|
||||
return !relativeClassName.parent().isRoot();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FqName asSingleFqName() {
|
||||
if (packageFqName.isRoot()) return relativeClassName;
|
||||
return new FqName(packageFqName.asString() + "." + relativeClassName.asString());
|
||||
}
|
||||
|
||||
public boolean startsWith(@NotNull Name segment) {
|
||||
return packageFqName.startsWith(segment);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string a string where packages are delimited by '/' and classes by '.', e.g. "kotlin/Map.Entry"
|
||||
*/
|
||||
@NotNull
|
||||
public static ClassId fromString(@NotNull String string) {
|
||||
return fromString(string, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassId fromString(@NotNull String string, boolean isLocal) {
|
||||
String packageName = StringsKt.substringBeforeLast(string, '/', "").replace('/', '.');
|
||||
String className = StringsKt.substringAfterLast(string, '/', string);
|
||||
return new ClassId(new FqName(packageName), new FqName(className), isLocal);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a string where packages are delimited by '/' and classes by '.', e.g. "kotlin/Map.Entry"
|
||||
*/
|
||||
@NotNull
|
||||
public String asString() {
|
||||
if (packageFqName.isRoot()) return relativeClassName.asString();
|
||||
return packageFqName.asString().replace('.', '/') + "/" + relativeClassName.asString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ClassId id = (ClassId) o;
|
||||
|
||||
return packageFqName.equals(id.packageFqName) &&
|
||||
relativeClassName.equals(id.relativeClassName) &&
|
||||
local == id.local;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = packageFqName.hashCode();
|
||||
result = 31 * result + relativeClassName.hashCode();
|
||||
result = 31 * result + Boolean.valueOf(local).hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return packageFqName.isRoot() ? "/" + asString() : asString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.name;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.utils.StringsKt;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class FqName {
|
||||
|
||||
@NotNull
|
||||
public static FqName fromSegments(@NotNull List<String> names) {
|
||||
return new FqName(StringsKt.join(names, "."));
|
||||
}
|
||||
|
||||
public static final FqName ROOT = new FqName("");
|
||||
|
||||
@NotNull
|
||||
private final FqNameUnsafe fqName;
|
||||
|
||||
// cache
|
||||
private transient FqName parent;
|
||||
|
||||
public FqName(@NotNull String fqName) {
|
||||
this.fqName = new FqNameUnsafe(fqName, this);
|
||||
}
|
||||
|
||||
public FqName(@NotNull FqNameUnsafe fqName) {
|
||||
this.fqName = fqName;
|
||||
}
|
||||
|
||||
private FqName(@NotNull FqNameUnsafe fqName, FqName parent) {
|
||||
this.fqName = fqName;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String asString() {
|
||||
return fqName.asString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FqNameUnsafe toUnsafe() {
|
||||
return fqName;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return fqName.isRoot();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FqName parent() {
|
||||
if (parent != null) {
|
||||
return parent;
|
||||
}
|
||||
|
||||
if (isRoot()) {
|
||||
throw new IllegalStateException("root");
|
||||
}
|
||||
|
||||
parent = new FqName(fqName.parent());
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FqName child(@NotNull Name name) {
|
||||
return new FqName(fqName.child(name), this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Name shortName() {
|
||||
return fqName.shortName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Name shortNameOrSpecial() {
|
||||
return fqName.shortNameOrSpecial();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Name> pathSegments() {
|
||||
return fqName.pathSegments();
|
||||
}
|
||||
|
||||
public boolean startsWith(@NotNull Name segment) {
|
||||
return fqName.startsWith(segment);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static FqName topLevel(@NotNull Name shortName) {
|
||||
return new FqName(FqNameUnsafe.topLevel(shortName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return fqName.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof FqName)) return false;
|
||||
|
||||
FqName otherFqName = (FqName) o;
|
||||
|
||||
if (!fqName.equals(otherFqName.fqName)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return fqName.hashCode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.name;
|
||||
|
||||
import kotlin.collections.ArraysKt;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Like {@link FqName} but allows '<' and '>' characters in name.
|
||||
*/
|
||||
public final class FqNameUnsafe {
|
||||
private static final Name ROOT_NAME = Name.special("<root>");
|
||||
private static final Pattern SPLIT_BY_DOTS = Pattern.compile("\\.");
|
||||
|
||||
private static final Function1<String, Name> STRING_TO_NAME = new Function1<String, Name>() {
|
||||
@Override
|
||||
public Name invoke(String name) {
|
||||
return Name.guessByFirstCharacter(name);
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
private final String fqName;
|
||||
|
||||
// cache
|
||||
private transient FqName safe;
|
||||
private transient FqNameUnsafe parent;
|
||||
private transient Name shortName;
|
||||
|
||||
FqNameUnsafe(@NotNull String fqName, @NotNull FqName safe) {
|
||||
this.fqName = fqName;
|
||||
this.safe = safe;
|
||||
}
|
||||
|
||||
public FqNameUnsafe(@NotNull String fqName) {
|
||||
this.fqName = fqName;
|
||||
}
|
||||
|
||||
private FqNameUnsafe(@NotNull String fqName, FqNameUnsafe parent, Name shortName) {
|
||||
this.fqName = fqName;
|
||||
this.parent = parent;
|
||||
this.shortName = shortName;
|
||||
}
|
||||
|
||||
public static boolean isValid(@Nullable String qualifiedName) {
|
||||
// TODO: There's a valid name with escape char ``
|
||||
return qualifiedName != null && qualifiedName.indexOf('/') < 0 && qualifiedName.indexOf('*') < 0;
|
||||
}
|
||||
|
||||
private void compute() {
|
||||
int lastDot = fqName.lastIndexOf('.');
|
||||
if (lastDot >= 0) {
|
||||
shortName = Name.guessByFirstCharacter(fqName.substring(lastDot + 1));
|
||||
parent = new FqNameUnsafe(fqName.substring(0, lastDot));
|
||||
}
|
||||
else {
|
||||
shortName = Name.guessByFirstCharacter(fqName);
|
||||
parent = FqName.ROOT.toUnsafe();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String asString() {
|
||||
return fqName;
|
||||
}
|
||||
|
||||
public boolean isSafe() {
|
||||
return safe != null || asString().indexOf('<') < 0;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FqName toSafe() {
|
||||
if (safe != null) {
|
||||
return safe;
|
||||
}
|
||||
safe = new FqName(this);
|
||||
return safe;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return fqName.isEmpty();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FqNameUnsafe parent() {
|
||||
if (parent != null) {
|
||||
return parent;
|
||||
}
|
||||
|
||||
if (isRoot()) {
|
||||
throw new IllegalStateException("root");
|
||||
}
|
||||
|
||||
compute();
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FqNameUnsafe child(@NotNull Name name) {
|
||||
String childFqName;
|
||||
if (isRoot()) {
|
||||
childFqName = name.asString();
|
||||
}
|
||||
else {
|
||||
childFqName = fqName + "." + name.asString();
|
||||
}
|
||||
return new FqNameUnsafe(childFqName, this, name);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Name shortName() {
|
||||
if (shortName != null) {
|
||||
return shortName;
|
||||
}
|
||||
|
||||
if (isRoot()) {
|
||||
throw new IllegalStateException("root");
|
||||
}
|
||||
|
||||
compute();
|
||||
|
||||
return shortName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Name shortNameOrSpecial() {
|
||||
if (isRoot()) {
|
||||
return ROOT_NAME;
|
||||
}
|
||||
else {
|
||||
return shortName();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Name> pathSegments() {
|
||||
return isRoot() ? Collections.<Name>emptyList() : ArraysKt.map(SPLIT_BY_DOTS.split(fqName), STRING_TO_NAME);
|
||||
}
|
||||
|
||||
public boolean startsWith(@NotNull Name segment) {
|
||||
if (isRoot())
|
||||
return false;
|
||||
|
||||
int firstDot = fqName.indexOf('.');
|
||||
return fqName.regionMatches(0, segment.asString(), 0, firstDot == -1 ? fqName.length() : firstDot);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static FqNameUnsafe topLevel(@NotNull Name shortName) {
|
||||
return new FqNameUnsafe(shortName.asString(), FqName.ROOT.toUnsafe(), shortName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String toString() {
|
||||
return isRoot() ? ROOT_NAME.asString() : fqName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof FqNameUnsafe)) return false;
|
||||
|
||||
FqNameUnsafe that = (FqNameUnsafe) o;
|
||||
|
||||
if (!fqName.equals(that.fqName)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return fqName.hashCode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.name
|
||||
|
||||
fun FqName.isSubpackageOf(packageName: FqName): Boolean {
|
||||
return when {
|
||||
this == packageName -> true
|
||||
packageName.isRoot -> true
|
||||
else -> isSubpackageOf(this.asString(), packageName.asString())
|
||||
}
|
||||
}
|
||||
|
||||
fun FqName.isChildOf(packageName: FqName): Boolean = parentOrNull() == packageName
|
||||
|
||||
private fun isSubpackageOf(subpackageNameStr: String, packageNameStr: String): Boolean {
|
||||
return subpackageNameStr.startsWith(packageNameStr) && subpackageNameStr[packageNameStr.length] == '.'
|
||||
}
|
||||
|
||||
fun FqName.isOneSegmentFQN(): Boolean = !isRoot && parent().isRoot
|
||||
|
||||
/**
|
||||
* Get the tail part of the FQ name by stripping a prefix. If FQ name does not begin with the given prefix, it will be returned as is.
|
||||
*
|
||||
* Examples:
|
||||
* "org.jetbrains.kotlin".tail("org") = "jetbrains.kotlin"
|
||||
* "org.jetbrains.kotlin".tail("") = "org.jetbrains.kotlin"
|
||||
* "org.jetbrains.kotlin".tail("org.jetbrains.kotlin") = ""
|
||||
* "org.jetbrains.kotlin".tail("org.jetbrains.gogland") = "org.jetbrains.kotlin"
|
||||
*/
|
||||
fun FqName.tail(prefix: FqName): FqName {
|
||||
return when {
|
||||
!isSubpackageOf(prefix) || prefix.isRoot -> this
|
||||
this == prefix -> FqName.ROOT
|
||||
else -> FqName(asString().substring(prefix.asString().length + 1))
|
||||
}
|
||||
}
|
||||
|
||||
fun FqName.parentOrNull(): FqName? = if (this.isRoot) null else parent()
|
||||
|
||||
private enum class State {
|
||||
BEGINNING,
|
||||
MIDDLE,
|
||||
AFTER_DOT
|
||||
}
|
||||
|
||||
// Check that it is javaName(\.javaName)* or an empty string
|
||||
fun isValidJavaFqName(qualifiedName: String?): Boolean {
|
||||
if (qualifiedName == null) return false
|
||||
|
||||
var state = State.BEGINNING
|
||||
|
||||
for (c in qualifiedName) {
|
||||
when (state) {
|
||||
State.BEGINNING, State.AFTER_DOT -> {
|
||||
if (!Character.isJavaIdentifierPart(c)) return false
|
||||
state = State.MIDDLE
|
||||
}
|
||||
State.MIDDLE -> {
|
||||
if (c == '.') {
|
||||
state = State.AFTER_DOT
|
||||
}
|
||||
else if (!Character.isJavaIdentifierPart(c)) return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return state != State.AFTER_DOT
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.name;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class Name implements Comparable<Name> {
|
||||
@NotNull
|
||||
private final String name;
|
||||
private final boolean special;
|
||||
|
||||
private Name(@NotNull String name, boolean special) {
|
||||
this.name = name;
|
||||
this.special = special;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String asString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getIdentifier() {
|
||||
if (special) {
|
||||
throw new IllegalStateException("not identifier: " + this);
|
||||
}
|
||||
return asString();
|
||||
}
|
||||
|
||||
public boolean isSpecial() {
|
||||
return special;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Name that) {
|
||||
return this.name.compareTo(that.name);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Name identifier(@NotNull String name) {
|
||||
return new Name(name, false);
|
||||
}
|
||||
|
||||
public static boolean isValidIdentifier(@NotNull String name) {
|
||||
if (name.isEmpty() || name.startsWith("<")) return false;
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
char ch = name.charAt(i);
|
||||
if (ch == '.' || ch == '/' || ch == '\\') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Name special(@NotNull String name) {
|
||||
if (!name.startsWith("<")) {
|
||||
throw new IllegalArgumentException("special name must start with '<': " + name);
|
||||
}
|
||||
return new Name(name, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Name guessByFirstCharacter(@NotNull String name) {
|
||||
if (name.startsWith("<")) {
|
||||
return special(name);
|
||||
}
|
||||
else {
|
||||
return identifier(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Name)) return false;
|
||||
|
||||
Name name1 = (Name) o;
|
||||
|
||||
if (special != name1.special) return false;
|
||||
if (!name.equals(name1.name)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = name.hashCode();
|
||||
result = 31 * result + (special ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.name
|
||||
|
||||
import java.util.*
|
||||
|
||||
object NameUtils {
|
||||
private val SANITIZE_AS_JAVA_INVALID_CHARACTERS = "[^\\p{L}\\p{Digit}]".toRegex()
|
||||
|
||||
@JvmStatic
|
||||
fun sanitizeAsJavaIdentifier(name: String): String {
|
||||
return SANITIZE_AS_JAVA_INVALID_CHARACTERS.replace(name, "_")
|
||||
}
|
||||
|
||||
/**
|
||||
* Capitalizes the short name of the file (without extension) and sanitizes it so that it's a valid Java identifier.
|
||||
* E.g. "fileName" -> "FileName", "1" -> "_1", "" -> "_"
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getPackagePartClassNamePrefix(shortFileName: String): String =
|
||||
if (shortFileName.isEmpty())
|
||||
"_"
|
||||
else
|
||||
capitalizeAsJavaClassName(sanitizeAsJavaIdentifier(shortFileName))
|
||||
|
||||
@JvmStatic
|
||||
private fun capitalizeAsJavaClassName(str: String): String =
|
||||
// NB use Locale.ENGLISH so that build is locale-independent.
|
||||
// See Javadoc on java.lang.String.toUpperCase() for more details.
|
||||
if (Character.isJavaIdentifierStart(str[0]))
|
||||
str.substring(0, 1).toUpperCase(Locale.ENGLISH) + str.substring(1)
|
||||
else
|
||||
"_$str"
|
||||
|
||||
// "pkg/someScript.kts" -> "SomeScript"
|
||||
@JvmStatic
|
||||
fun getScriptNameForFile(filePath: String): Name =
|
||||
Name.identifier(NameUtils.getPackagePartClassNamePrefix(filePath.substringAfterLast('/').substringBeforeLast('.')))
|
||||
|
||||
@JvmStatic
|
||||
fun hasName(name: Name) = name != SpecialNames.NO_NAME_PROVIDED && name != SpecialNames.ANONYMOUS_FUNCTION
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.name;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class SpecialNames {
|
||||
public static final Name NO_NAME_PROVIDED = Name.special("<no name provided>");
|
||||
public static final Name ROOT_PACKAGE = Name.special("<root package>");
|
||||
|
||||
public static final Name DEFAULT_NAME_FOR_COMPANION_OBJECT = Name.identifier("Companion");
|
||||
|
||||
// This name is used as a key for the case when something has no name _due to a syntactic error_
|
||||
// Example: fun (x: Int) = 5
|
||||
// There's no name for this function in the PSI
|
||||
// The name contains a GUID to avoid clashes, if a clash happens, it's not a big deal: the code does not compile anyway
|
||||
public static final Name SAFE_IDENTIFIER_FOR_NO_NAME = Name.identifier("no_name_in_PSI_3d19d79d_1ba9_4cd0_b7f5_b46aa3cd5d40");
|
||||
|
||||
public static final String ANONYMOUS = "<anonymous>";
|
||||
public static final Name ANONYMOUS_FUNCTION = Name.special(ANONYMOUS);
|
||||
|
||||
@NotNull
|
||||
public static Name safeIdentifier(@Nullable Name name) {
|
||||
return name != null && !name.isSpecial() ? name : SAFE_IDENTIFIER_FOR_NO_NAME;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Name safeIdentifier(@Nullable String name) {
|
||||
return safeIdentifier(name == null ? null : Name.identifier(name));
|
||||
}
|
||||
|
||||
public static boolean isSafeIdentifier(@NotNull Name name) {
|
||||
return !name.asString().isEmpty() && !name.isSpecial();
|
||||
}
|
||||
|
||||
private SpecialNames() {}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.platform
|
||||
|
||||
/**
|
||||
* Core abstraction of Platform API, represents a collection of platforms.
|
||||
*
|
||||
* This is the primarily abstraction intended to use in the most part of API, as, usually,
|
||||
* pretty much anything that may have a platform, may have a several platforms as well in the
|
||||
* context of multiplatform projects.
|
||||
*
|
||||
* Please, use it over the [SimplePlatform] unless you're absolutely sure what you're doing.
|
||||
*
|
||||
* NB. Even in cases, where some part of logic makes sense only for a particular platform (e.g., JVM),
|
||||
* it still can be applicable for [TargetPlatform]s with [componentPlatforms] > 1, e.g. when it consists
|
||||
* of two version of JDK, JDK and Android, several versions of Android API, etc.
|
||||
*/
|
||||
open class TargetPlatform(val componentPlatforms: Set<SimplePlatform>) : Collection<SimplePlatform> by componentPlatforms {
|
||||
init {
|
||||
if (componentPlatforms.isEmpty()) throw IllegalArgumentException("Don't instantiate TargetPlatform with empty set of platforms")
|
||||
}
|
||||
|
||||
override fun toString(): String = presentableDescription
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
||||
if (other !is TargetPlatform) return false
|
||||
|
||||
if (componentPlatforms != other.componentPlatforms) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return componentPlatforms.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Core abstraction of Platform API, represents exactly one platform.
|
||||
*
|
||||
* API guarantees:
|
||||
*
|
||||
* - direct inheritors are well-known and represent three major platforms supported at the moment (JVM, JS, Native)
|
||||
*
|
||||
* - exact enumeration of all inheritors isn't available at the compile time, see [CommonPlatforms]
|
||||
*
|
||||
* - each implementation should support equality in a broad sense of "absolutely the same platform"
|
||||
*
|
||||
* - it is _prohibited_ to create instances of [SimplePlatform] in the client's code, use respective factory instance (e.g., [JvmPlatforms])
|
||||
* to get instances of platforms
|
||||
*
|
||||
* Ideally, each specific subtype should be either a data class or singleton.
|
||||
*/
|
||||
abstract class SimplePlatform(val platformName: String) {
|
||||
override fun toString(): String {
|
||||
val targetName = targetName
|
||||
return if (targetName.isNotEmpty()) "$platformName ($targetName)" else platformName
|
||||
}
|
||||
|
||||
// description of TargetPlatformVersion or name of custom platform-specific target; used in serialization
|
||||
open val targetName: String
|
||||
get() = targetPlatformVersion.description
|
||||
|
||||
/** See KDoc for [TargetPlatform.oldFashionedDescription] */
|
||||
abstract val oldFashionedDescription: String
|
||||
|
||||
// FIXME(dsavvinov): hack to allow injection inject JvmTarget into container.
|
||||
// Proper fix would be to rewrite clients to get JdkPlatform from container, and pull JvmTarget from it
|
||||
// (this will also remove need in TargetPlatformVersion as the whole, and, in particular, ugly passing
|
||||
// of TargetPlatformVersion.NoVersion in non-JVM code)
|
||||
open val targetPlatformVersion: TargetPlatformVersion = TargetPlatformVersion.NoVersion
|
||||
}
|
||||
|
||||
interface TargetPlatformVersion {
|
||||
val description: String
|
||||
|
||||
object NoVersion : TargetPlatformVersion {
|
||||
override val description = ""
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this is a [TargetPlatform] that targets multiple [SimplePlatform]s.
|
||||
*/
|
||||
fun TargetPlatform?.isMultiPlatform(): Boolean = this != null && size > 1
|
||||
|
||||
/**
|
||||
* Whether this is "Common" platform in its classical sense (MPP v1).
|
||||
*/
|
||||
fun TargetPlatform?.isCommon(): Boolean = isMultiPlatform() && this!!.iterator().let { i ->
|
||||
val firstPlatformName = i.next().platformName
|
||||
while (i.hasNext()) {
|
||||
if (i.next().platformName != firstPlatformName) return@let true
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fun SimplePlatform.toTargetPlatform(): TargetPlatform = TargetPlatform(setOf(this))
|
||||
|
||||
fun SimplePlatform.serializeToString(): String = "$platformName [$targetName]"
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.platform
|
||||
|
||||
inline fun <reified T : SimplePlatform> TargetPlatform.subplatformsOfType(): List<T> = componentPlatforms.filterIsInstance<T>()
|
||||
fun <T> TargetPlatform.subplatformsOfType(klass: Class<T>): List<T> = componentPlatforms.filterIsInstance(klass)
|
||||
|
||||
inline fun <reified T : SimplePlatform> TargetPlatform?.has(): Boolean = this != null && subplatformsOfType<T>().isNotEmpty()
|
||||
fun <T> TargetPlatform?.has(klass: Class<T>): Boolean = this != null && subplatformsOfType(klass).isNotEmpty()
|
||||
|
||||
|
||||
/**
|
||||
* Returns human-readable description, mapping multiplatform to 'Common (experimental)',
|
||||
* as well as maintaining some quirks of the previous representation, like trailing whitespaces
|
||||
*
|
||||
* It is needed mainly for backwards compatibility, because some subsystem actually
|
||||
* managed to rely on the format of that string. In particular, 'facetSerialization.kt' uses
|
||||
* those string as keys in serialized `.iml`-file, and changing format of that string (including
|
||||
* trimming pointless whitespaces) leads to incorrectly deserialized facets.
|
||||
*
|
||||
* New clients are encouraged to use [presentableDescription] description instead, as it
|
||||
* also provides better description for multiplatforms.
|
||||
*/
|
||||
val TargetPlatform.oldFashionedDescription: String
|
||||
// this method mistakenly detects "common native" platform as "Common (experimental)"
|
||||
// though this does not seem to have any significant effect
|
||||
get() = this.singleOrNull()?.oldFashionedDescription ?: "Common (experimental) "
|
||||
|
||||
|
||||
/**
|
||||
* Renders multiplatform in form
|
||||
* '$PLATFORM_1/$PLATFORM_2/...'
|
||||
* e.g.
|
||||
* 'JVM (1.8)/JS/Native (ios_x64)'
|
||||
*/
|
||||
val TargetPlatform.presentableDescription: String
|
||||
get() = componentPlatforms.joinToString(separator = "/")
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
*
|
||||
* 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.renderer;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
|
||||
/** This class is generated by {@link "org.jetbrains.kotlin.generators.frontend.GenerateKeywordStrings"}. DO NOT MODIFY MANUALLY */
|
||||
public class KeywordStringsGenerated {
|
||||
private KeywordStringsGenerated() {}
|
||||
|
||||
public static final Set<String> KEYWORDS = new HashSet<String>(Arrays.asList(
|
||||
"package",
|
||||
"as",
|
||||
"typealias",
|
||||
"class",
|
||||
"this",
|
||||
"super",
|
||||
"val",
|
||||
"var",
|
||||
"fun",
|
||||
"for",
|
||||
"null",
|
||||
"true",
|
||||
"false",
|
||||
"is",
|
||||
"in",
|
||||
"throw",
|
||||
"return",
|
||||
"break",
|
||||
"continue",
|
||||
"object",
|
||||
"if",
|
||||
"try",
|
||||
"else",
|
||||
"while",
|
||||
"do",
|
||||
"when",
|
||||
"interface",
|
||||
"typeof"
|
||||
));
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.renderer
|
||||
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
fun Name.render(): String {
|
||||
return if (this.shouldBeEscaped()) '`' + asString() + '`' else asString()
|
||||
}
|
||||
|
||||
private fun Name.shouldBeEscaped(): Boolean {
|
||||
if (isSpecial) return false
|
||||
|
||||
val string = asString()
|
||||
return string in KeywordStringsGenerated.KEYWORDS || string.any { !Character.isLetterOrDigit(it) && it != '_' }
|
||||
}
|
||||
|
||||
fun FqNameUnsafe.render(): String {
|
||||
return renderFqName(pathSegments())
|
||||
}
|
||||
|
||||
fun FqName.render(): String {
|
||||
return renderFqName(pathSegments())
|
||||
}
|
||||
|
||||
fun renderFqName(pathSegments: List<Name>): String {
|
||||
return buildString {
|
||||
for (element in pathSegments) {
|
||||
if (length > 0) {
|
||||
append(".")
|
||||
}
|
||||
append(element.render())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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.serialization.deserialization
|
||||
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
|
||||
data class IncompatibleVersionErrorData<out T>(
|
||||
val actualVersion: T,
|
||||
val expectedVersion: T,
|
||||
val filePath: String,
|
||||
val classId: ClassId
|
||||
)
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.serialization.deserialization.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
|
||||
|
||||
interface DeserializedContainerSource : SourceElement {
|
||||
// Non-null if this container is loaded from a class with an incompatible binary version
|
||||
val incompatibility: IncompatibleVersionErrorData<*>?
|
||||
|
||||
// True iff this is container is "invisible" because it's loaded from a pre-release class and this compiler is a release
|
||||
val isPreReleaseInvisible: Boolean
|
||||
|
||||
// True iff this container was compiled by the new IR backend, this compiler is not using the IR backend right now,
|
||||
// and no additional flags to override this behavior were specified.
|
||||
val isInvisibleIrDependency: Boolean
|
||||
|
||||
// This string should only be used in error messages
|
||||
val presentableString: String
|
||||
}
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.types
|
||||
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeSystemContext
|
||||
|
||||
object AbstractStrictEqualityTypeChecker {
|
||||
fun strictEqualTypes(context: TypeSystemContext, a: KotlinTypeMarker, b: KotlinTypeMarker) = context.strictEqualTypesInternal(a, b)
|
||||
|
||||
/**
|
||||
* Note that:
|
||||
* - `String!` != `String`
|
||||
* - `A<String!>` != `A<String>`
|
||||
* - `A<in Nothing>` != `A<out Any?>`
|
||||
* - `A<*>` != `A<out Any?>`
|
||||
*
|
||||
* Also different error types are not equal even if errorTypeEqualToAnything is true
|
||||
*/
|
||||
private fun TypeSystemContext.strictEqualTypesInternal(a: KotlinTypeMarker, b: KotlinTypeMarker): Boolean {
|
||||
if (a === b) return true
|
||||
|
||||
val simpleA = a.asSimpleType()
|
||||
val simpleB = b.asSimpleType()
|
||||
if (simpleA != null && simpleB != null) return strictEqualSimpleTypes(simpleA, simpleB)
|
||||
|
||||
val flexibleA = a.asFlexibleType()
|
||||
val flexibleB = b.asFlexibleType()
|
||||
if (flexibleA != null && flexibleB != null) {
|
||||
return strictEqualSimpleTypes(flexibleA.lowerBound(), flexibleB.lowerBound()) &&
|
||||
strictEqualSimpleTypes(flexibleA.upperBound(), flexibleB.upperBound())
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun TypeSystemContext.strictEqualSimpleTypes(a: SimpleTypeMarker, b: SimpleTypeMarker): Boolean {
|
||||
if (a.argumentsCount() != b.argumentsCount()
|
||||
|| a.isMarkedNullable() != b.isMarkedNullable()
|
||||
|| (a.asDefinitelyNotNullType() == null) != (b.asDefinitelyNotNullType() == null)
|
||||
|| !isEqualTypeConstructors(a.typeConstructor(), b.typeConstructor())
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (identicalArguments(a, b)) return true
|
||||
|
||||
for (i in 0 until a.argumentsCount()) {
|
||||
val aArg = a.getArgument(i)
|
||||
val bArg = b.getArgument(i)
|
||||
if (aArg.isStarProjection() != bArg.isStarProjection()) return false
|
||||
|
||||
// both non-star
|
||||
if (!aArg.isStarProjection()) {
|
||||
if (aArg.getVariance() != bArg.getVariance()) return false
|
||||
if (!strictEqualTypesInternal(aArg.getType(), bArg.getType())) return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,613 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.types
|
||||
|
||||
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext.LowerCapturedTypePolicy.*
|
||||
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext.SupertypesPolicy
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.SmartSet
|
||||
import java.util.*
|
||||
|
||||
|
||||
abstract class AbstractTypeCheckerContext : TypeSystemContext {
|
||||
|
||||
|
||||
abstract fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy
|
||||
|
||||
abstract fun areEqualTypeConstructors(a: TypeConstructorMarker, b: TypeConstructorMarker): Boolean
|
||||
|
||||
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
return type
|
||||
}
|
||||
|
||||
open fun refineType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
return type
|
||||
}
|
||||
|
||||
open fun customIsSubtypeOf(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean = true
|
||||
|
||||
abstract val isErrorTypeEqualsToAnything: Boolean
|
||||
|
||||
abstract val isStubTypeEqualsToAnything: Boolean
|
||||
|
||||
protected var argumentsDepth = 0
|
||||
|
||||
|
||||
internal inline fun <T> runWithArgumentsSettings(subArgument: KotlinTypeMarker, f: AbstractTypeCheckerContext.() -> T): T {
|
||||
if (argumentsDepth > 100) {
|
||||
error("Arguments depth is too high. Some related argument: $subArgument")
|
||||
}
|
||||
|
||||
argumentsDepth++
|
||||
val result = f()
|
||||
argumentsDepth--
|
||||
return result
|
||||
}
|
||||
|
||||
open fun getLowerCapturedTypePolicy(subType: SimpleTypeMarker, superType: CapturedTypeMarker): LowerCapturedTypePolicy = CHECK_SUBTYPE_AND_LOWER
|
||||
|
||||
open fun addSubtypeConstraint(
|
||||
subType: KotlinTypeMarker,
|
||||
superType: KotlinTypeMarker,
|
||||
isFromNullabilityConstraint: Boolean = false
|
||||
): Boolean? = null
|
||||
|
||||
enum class LowerCapturedTypePolicy {
|
||||
CHECK_ONLY_LOWER,
|
||||
CHECK_SUBTYPE_AND_LOWER,
|
||||
SKIP_LOWER
|
||||
}
|
||||
|
||||
private var supertypesLocked = false
|
||||
|
||||
var supertypesDeque: ArrayDeque<SimpleTypeMarker>? = null
|
||||
private set
|
||||
var supertypesSet: MutableSet<SimpleTypeMarker>? = null
|
||||
private set
|
||||
|
||||
|
||||
fun initialize() {
|
||||
assert(!supertypesLocked)
|
||||
supertypesLocked = true
|
||||
|
||||
if (supertypesDeque == null) {
|
||||
supertypesDeque = ArrayDeque(4)
|
||||
}
|
||||
if (supertypesSet == null) {
|
||||
supertypesSet = SmartSet.create()
|
||||
}
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
supertypesDeque!!.clear()
|
||||
supertypesSet!!.clear()
|
||||
supertypesLocked = false
|
||||
}
|
||||
|
||||
inline fun anySupertype(
|
||||
start: SimpleTypeMarker,
|
||||
predicate: (SimpleTypeMarker) -> Boolean,
|
||||
supertypesPolicy: (SimpleTypeMarker) -> SupertypesPolicy
|
||||
): Boolean {
|
||||
if (predicate(start)) return true
|
||||
|
||||
initialize()
|
||||
|
||||
val deque = supertypesDeque!!
|
||||
val visitedSupertypes = supertypesSet!!
|
||||
|
||||
deque.push(start)
|
||||
while (deque.isNotEmpty()) {
|
||||
if (visitedSupertypes.size > 1000) {
|
||||
error("Too many supertypes for type: $start. Supertypes = ${visitedSupertypes.joinToString()}")
|
||||
}
|
||||
val current = deque.pop()
|
||||
if (!visitedSupertypes.add(current)) continue
|
||||
|
||||
val policy = supertypesPolicy(current).takeIf { it != SupertypesPolicy.None } ?: continue
|
||||
for (supertype in current.typeConstructor().supertypes()) {
|
||||
val newType = policy.transformType(this, supertype)
|
||||
if (predicate(newType)) {
|
||||
clear()
|
||||
return true
|
||||
}
|
||||
deque.add(newType)
|
||||
}
|
||||
}
|
||||
|
||||
clear()
|
||||
return false
|
||||
}
|
||||
|
||||
sealed class SupertypesPolicy {
|
||||
abstract fun transformType(context: AbstractTypeCheckerContext, type: KotlinTypeMarker): SimpleTypeMarker
|
||||
|
||||
object None : SupertypesPolicy() {
|
||||
override fun transformType(context: AbstractTypeCheckerContext, type: KotlinTypeMarker) =
|
||||
throw UnsupportedOperationException("Should not be called")
|
||||
}
|
||||
|
||||
object UpperIfFlexible : SupertypesPolicy() {
|
||||
override fun transformType(context: AbstractTypeCheckerContext, type: KotlinTypeMarker) =
|
||||
with(context) { type.upperBoundIfFlexible() }
|
||||
}
|
||||
|
||||
object LowerIfFlexible : SupertypesPolicy() {
|
||||
override fun transformType(context: AbstractTypeCheckerContext, type: KotlinTypeMarker) =
|
||||
with(context) { type.lowerBoundIfFlexible() }
|
||||
}
|
||||
|
||||
abstract class DoCustomTransform : SupertypesPolicy()
|
||||
}
|
||||
|
||||
abstract val KotlinTypeMarker.isAllowedTypeVariable: Boolean
|
||||
}
|
||||
|
||||
object AbstractTypeChecker {
|
||||
@JvmField
|
||||
var RUN_SLOW_ASSERTIONS = false
|
||||
|
||||
fun isSubtypeOf(
|
||||
context: TypeCheckerProviderContext,
|
||||
subType: KotlinTypeMarker,
|
||||
superType: KotlinTypeMarker,
|
||||
stubTypesEqualToAnything: Boolean = true
|
||||
): Boolean {
|
||||
return AbstractTypeChecker.isSubtypeOf(context.newBaseTypeCheckerContext(true, stubTypesEqualToAnything), subType, superType)
|
||||
}
|
||||
|
||||
fun equalTypes(
|
||||
context: TypeCheckerProviderContext,
|
||||
a: KotlinTypeMarker,
|
||||
b: KotlinTypeMarker,
|
||||
stubTypesEqualToAnything: Boolean = true
|
||||
): Boolean {
|
||||
return AbstractTypeChecker.equalTypes(context.newBaseTypeCheckerContext(false, stubTypesEqualToAnything), a, b)
|
||||
}
|
||||
|
||||
fun isSubtypeOf(
|
||||
context: AbstractTypeCheckerContext,
|
||||
subType: KotlinTypeMarker,
|
||||
superType: KotlinTypeMarker,
|
||||
isFromNullabilityConstraint: Boolean = false
|
||||
): Boolean {
|
||||
if (subType === superType) return true
|
||||
|
||||
if (!context.customIsSubtypeOf(subType, superType)) return false
|
||||
|
||||
return with(context) {
|
||||
completeIsSubTypeOf(prepareType(refineType(subType)), prepareType(refineType(superType)), isFromNullabilityConstraint)
|
||||
}
|
||||
}
|
||||
|
||||
fun equalTypes(context: AbstractTypeCheckerContext, a: KotlinTypeMarker, b: KotlinTypeMarker): Boolean = with(context) {
|
||||
if (a === b) return true
|
||||
|
||||
if (isCommonDenotableType(a) && isCommonDenotableType(b)) {
|
||||
val refinedA = refineType(a)
|
||||
val refinedB = refineType(b)
|
||||
val simpleA = refinedA.lowerBoundIfFlexible()
|
||||
if (!areEqualTypeConstructors(refinedA.typeConstructor(), refinedB.typeConstructor())) return false
|
||||
if (simpleA.argumentsCount() == 0) {
|
||||
if (refinedA.hasFlexibleNullability() || refinedB.hasFlexibleNullability()) return true
|
||||
|
||||
return simpleA.isMarkedNullable() == refinedB.lowerBoundIfFlexible().isMarkedNullable()
|
||||
}
|
||||
}
|
||||
|
||||
return isSubtypeOf(context, a, b) && isSubtypeOf(context, b, a)
|
||||
}
|
||||
|
||||
|
||||
private fun AbstractTypeCheckerContext.completeIsSubTypeOf(
|
||||
subType: KotlinTypeMarker,
|
||||
superType: KotlinTypeMarker,
|
||||
isFromNullabilityConstraint: Boolean
|
||||
): Boolean {
|
||||
checkSubtypeForSpecialCases(subType.lowerBoundIfFlexible(), superType.upperBoundIfFlexible())?.let {
|
||||
addSubtypeConstraint(subType, superType, isFromNullabilityConstraint)
|
||||
return it
|
||||
}
|
||||
|
||||
// we should add constraints with flexible types, otherwise we never get flexible type as answer in constraint system
|
||||
addSubtypeConstraint(subType, superType, isFromNullabilityConstraint)?.let { return it }
|
||||
|
||||
return isSubtypeOfForSingleClassifierType(subType.lowerBoundIfFlexible(), superType.upperBoundIfFlexible())
|
||||
}
|
||||
|
||||
private fun AbstractTypeCheckerContext.checkSubtypeForIntegerLiteralType(subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean? {
|
||||
if (!subType.isIntegerLiteralType() && !superType.isIntegerLiteralType()) return null
|
||||
|
||||
fun typeInIntegerLiteralType(integerLiteralType: SimpleTypeMarker, type: SimpleTypeMarker, checkSupertypes: Boolean): Boolean =
|
||||
integerLiteralType.possibleIntegerTypes().any { possibleType ->
|
||||
(possibleType.typeConstructor() == type.typeConstructor()) || (checkSupertypes && isSubtypeOf(this, type, possibleType))
|
||||
}
|
||||
|
||||
when {
|
||||
subType.isIntegerLiteralType() && superType.isIntegerLiteralType() -> {
|
||||
return true
|
||||
}
|
||||
|
||||
subType.isIntegerLiteralType() -> {
|
||||
if (typeInIntegerLiteralType(subType, superType, checkSupertypes = false)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
superType.isIntegerLiteralType() -> {
|
||||
// Here we also have to check supertypes for intersection types: { Int & String } <: IntegerLiteralTypes
|
||||
if (typeInIntegerLiteralType(superType, subType, checkSupertypes = true)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun AbstractTypeCheckerContext.hasNothingSupertype(type: SimpleTypeMarker): Boolean {
|
||||
val typeConstructor = type.typeConstructor()
|
||||
if (typeConstructor.isClassTypeConstructor()) {
|
||||
return typeConstructor.isNothingConstructor()
|
||||
}
|
||||
return anySupertype(type, { it.typeConstructor().isNothingConstructor() }) {
|
||||
if (it.isClassType()) {
|
||||
SupertypesPolicy.None
|
||||
} else {
|
||||
SupertypesPolicy.LowerIfFlexible
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun AbstractTypeCheckerContext.isSubtypeOfForSingleClassifierType(subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean {
|
||||
if (AbstractTypeChecker.RUN_SLOW_ASSERTIONS) {
|
||||
assert(subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || subType.isAllowedTypeVariable) {
|
||||
"Not singleClassifierType and not intersection subType: $subType"
|
||||
}
|
||||
assert(superType.isSingleClassifierType() || superType.isAllowedTypeVariable) {
|
||||
"Not singleClassifierType superType: $superType"
|
||||
}
|
||||
}
|
||||
|
||||
if (!AbstractNullabilityChecker.isPossibleSubtype(this, subType, superType)) return false
|
||||
|
||||
checkSubtypeForIntegerLiteralType(subType.lowerBoundIfFlexible(), superType.upperBoundIfFlexible())?.let {
|
||||
addSubtypeConstraint(subType, superType)
|
||||
return it
|
||||
}
|
||||
|
||||
val superConstructor = superType.typeConstructor()
|
||||
|
||||
if (isEqualTypeConstructors(subType.typeConstructor(), superConstructor) && superConstructor.parametersCount() == 0) return true
|
||||
if (superType.typeConstructor().isAnyConstructor()) return true
|
||||
|
||||
val supertypesWithSameConstructor = findCorrespondingSupertypes(subType, superConstructor)
|
||||
when (supertypesWithSameConstructor.size) {
|
||||
0 -> return hasNothingSupertype(subType) // todo Nothing & Array<Number> <: Array<String>
|
||||
1 -> return isSubtypeForSameConstructor(supertypesWithSameConstructor.first().asArgumentList(), superType)
|
||||
|
||||
else -> { // at least 2 supertypes with same constructors. Such case is rare
|
||||
val newArguments = ArgumentList(superConstructor.parametersCount())
|
||||
var anyNonOutParameter = false
|
||||
for (index in 0 until superConstructor.parametersCount()) {
|
||||
anyNonOutParameter = anyNonOutParameter || superConstructor.getParameter(index).getVariance() != TypeVariance.OUT
|
||||
if (anyNonOutParameter) continue
|
||||
val allProjections = supertypesWithSameConstructor.map {
|
||||
it.getArgumentOrNull(index)?.takeIf { it.getVariance() == TypeVariance.INV }?.getType()
|
||||
?: error("Incorrect type: $it, subType: $subType, superType: $superType")
|
||||
}
|
||||
|
||||
// todo discuss
|
||||
val intersection = intersectTypes(allProjections).asTypeArgument()
|
||||
newArguments.add(intersection)
|
||||
}
|
||||
|
||||
if (!anyNonOutParameter && isSubtypeForSameConstructor(newArguments, superType)) return true
|
||||
|
||||
// TODO: rethink this; now components order in intersection type affects semantic due to run subtyping (which can add constraints) only until the first successful candidate
|
||||
return supertypesWithSameConstructor.any { isSubtypeForSameConstructor(it.asArgumentList(), superType) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun AbstractTypeCheckerContext.isSubtypeForSameConstructor(
|
||||
capturedSubArguments: TypeArgumentListMarker,
|
||||
superType: SimpleTypeMarker
|
||||
): Boolean {
|
||||
// No way to check, as no index sometimes
|
||||
//if (capturedSubArguments === superType.arguments) return true
|
||||
|
||||
//val parameters = superType.constructor.parameters
|
||||
val superTypeConstructor = superType.typeConstructor()
|
||||
for (index in 0 until superTypeConstructor.parametersCount()) {
|
||||
val superProjection = superType.getArgument(index) // todo error index
|
||||
if (superProjection.isStarProjection()) continue // A<B> <: A<*>
|
||||
|
||||
val superArgumentType = superProjection.getType()
|
||||
val subArgumentType = capturedSubArguments[index].let {
|
||||
assert(it.getVariance() == TypeVariance.INV) { "Incorrect sub argument: $it" }
|
||||
it.getType()
|
||||
}
|
||||
|
||||
val variance = effectiveVariance(superTypeConstructor.getParameter(index).getVariance(), superProjection.getVariance())
|
||||
?: return isErrorTypeEqualsToAnything // todo exception?
|
||||
|
||||
val correctArgument = runWithArgumentsSettings(subArgumentType) {
|
||||
when (variance) {
|
||||
TypeVariance.INV -> equalTypes(this, subArgumentType, superArgumentType)
|
||||
TypeVariance.OUT -> isSubtypeOf(this, subArgumentType, superArgumentType)
|
||||
TypeVariance.IN -> isSubtypeOf(this, superArgumentType, subArgumentType)
|
||||
}
|
||||
}
|
||||
if (!correctArgument) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun AbstractTypeCheckerContext.isCommonDenotableType(type: KotlinTypeMarker): Boolean =
|
||||
type.typeConstructor().isDenotable() &&
|
||||
!type.isDynamic() && !type.isDefinitelyNotNullType() &&
|
||||
type.lowerBoundIfFlexible().typeConstructor() == type.upperBoundIfFlexible().typeConstructor()
|
||||
|
||||
fun effectiveVariance(declared: TypeVariance, useSite: TypeVariance): TypeVariance? {
|
||||
if (declared == TypeVariance.INV) return useSite
|
||||
if (useSite == TypeVariance.INV) return declared
|
||||
|
||||
// both not INVARIANT
|
||||
if (declared == useSite) return declared
|
||||
|
||||
// composite In with Out
|
||||
return null
|
||||
}
|
||||
|
||||
private fun AbstractTypeCheckerContext.checkSubtypeForSpecialCases(subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean? {
|
||||
if (subType.isError() || superType.isError()) {
|
||||
if (isErrorTypeEqualsToAnything) return true
|
||||
|
||||
if (subType.isMarkedNullable() && !superType.isMarkedNullable()) return false
|
||||
|
||||
return AbstractStrictEqualityTypeChecker.strictEqualTypes(
|
||||
this,
|
||||
subType.withNullability(false),
|
||||
superType.withNullability(false)
|
||||
)
|
||||
}
|
||||
|
||||
if (subType.isStubType() || superType.isStubType()) return isStubTypeEqualsToAnything
|
||||
|
||||
val superTypeCaptured = superType.asCapturedType()
|
||||
val lowerType = superTypeCaptured?.lowerType()
|
||||
if (superTypeCaptured != null && lowerType != null) {
|
||||
when (getLowerCapturedTypePolicy(subType, superTypeCaptured)) {
|
||||
CHECK_ONLY_LOWER -> return isSubtypeOf(this, subType, lowerType)
|
||||
CHECK_SUBTYPE_AND_LOWER -> if (isSubtypeOf(this, subType, lowerType)) return true
|
||||
SKIP_LOWER -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
val superTypeConstructor = superType.typeConstructor()
|
||||
if (superTypeConstructor.isIntersection()) {
|
||||
assert(!superType.isMarkedNullable()) { "Intersection type should not be marked nullable!: $superType" }
|
||||
|
||||
return superTypeConstructor.supertypes().all { isSubtypeOf(this, subType, it) }
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
private fun AbstractTypeCheckerContext.collectAllSupertypesWithGivenTypeConstructor(
|
||||
subType: SimpleTypeMarker,
|
||||
superConstructor: TypeConstructorMarker
|
||||
): List<SimpleTypeMarker> {
|
||||
subType.fastCorrespondingSupertypes(superConstructor)?.let {
|
||||
return it
|
||||
}
|
||||
|
||||
if (!superConstructor.isClassTypeConstructor() && subType.isClassType()) return emptyList()
|
||||
|
||||
if (superConstructor.isCommonFinalClassConstructor()) {
|
||||
return if (areEqualTypeConstructors(subType.typeConstructor(), superConstructor))
|
||||
listOf(captureFromArguments(subType, CaptureStatus.FOR_SUBTYPING) ?: subType)
|
||||
else
|
||||
emptyList()
|
||||
}
|
||||
|
||||
val result: MutableList<SimpleTypeMarker> = SmartList()
|
||||
|
||||
anySupertype(subType, { false }) {
|
||||
|
||||
val current = captureFromArguments(it, CaptureStatus.FOR_SUBTYPING) ?: it
|
||||
|
||||
when {
|
||||
areEqualTypeConstructors(current.typeConstructor(), superConstructor) -> {
|
||||
result.add(current)
|
||||
SupertypesPolicy.None
|
||||
}
|
||||
current.argumentsCount() == 0 -> {
|
||||
SupertypesPolicy.LowerIfFlexible
|
||||
}
|
||||
else -> {
|
||||
substitutionSupertypePolicy(current)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun AbstractTypeCheckerContext.collectAndFilter(classType: SimpleTypeMarker, constructor: TypeConstructorMarker) =
|
||||
selectOnlyPureKotlinSupertypes(collectAllSupertypesWithGivenTypeConstructor(classType, constructor))
|
||||
|
||||
|
||||
/**
|
||||
* If we have several paths to some interface, we should prefer pure kotlin path.
|
||||
* Example:
|
||||
*
|
||||
* class MyList : AbstractList<String>(), MutableList<String>
|
||||
*
|
||||
* We should see `String` in `get` function and others, also MyList is not subtype of MutableList<String?>
|
||||
*
|
||||
* More tests: javaAndKotlinSuperType & purelyImplementedCollection folder
|
||||
*/
|
||||
private fun AbstractTypeCheckerContext.selectOnlyPureKotlinSupertypes(supertypes: List<SimpleTypeMarker>): List<SimpleTypeMarker> {
|
||||
if (supertypes.size < 2) return supertypes
|
||||
|
||||
val allPureSupertypes = supertypes.filter {
|
||||
it.asArgumentList().all(this) { it.getType().asFlexibleType() == null }
|
||||
}
|
||||
return if (allPureSupertypes.isNotEmpty()) allPureSupertypes else supertypes
|
||||
}
|
||||
|
||||
|
||||
// nullability was checked earlier via nullabilityChecker
|
||||
// should be used only if you really sure that it is correct
|
||||
fun AbstractTypeCheckerContext.findCorrespondingSupertypes(
|
||||
subType: SimpleTypeMarker,
|
||||
superConstructor: TypeConstructorMarker
|
||||
): List<SimpleTypeMarker> {
|
||||
if (subType.isClassType()) {
|
||||
return collectAndFilter(subType, superConstructor)
|
||||
}
|
||||
|
||||
// i.e. superType is not a classType
|
||||
if (!superConstructor.isClassTypeConstructor() && !superConstructor.isIntegerLiteralTypeConstructor()) {
|
||||
return collectAllSupertypesWithGivenTypeConstructor(subType, superConstructor)
|
||||
}
|
||||
|
||||
// todo add tests
|
||||
val classTypeSupertypes = SmartList<SimpleTypeMarker>()
|
||||
anySupertype(subType, { false }) {
|
||||
if (it.isClassType()) {
|
||||
classTypeSupertypes.add(it)
|
||||
SupertypesPolicy.None
|
||||
} else {
|
||||
SupertypesPolicy.LowerIfFlexible
|
||||
}
|
||||
}
|
||||
|
||||
return classTypeSupertypes.flatMap { collectAndFilter(it, superConstructor) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object AbstractNullabilityChecker {
|
||||
// this method checks only nullability
|
||||
fun isPossibleSubtype(context: AbstractTypeCheckerContext, subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean =
|
||||
context.runIsPossibleSubtype(subType, superType)
|
||||
|
||||
fun isSubtypeOfAny(context: TypeCheckerProviderContext, type: KotlinTypeMarker): Boolean =
|
||||
AbstractNullabilityChecker.isSubtypeOfAny(
|
||||
context.newBaseTypeCheckerContext(
|
||||
errorTypesEqualToAnything = false,
|
||||
stubTypesEqualToAnything = true
|
||||
),
|
||||
type
|
||||
)
|
||||
|
||||
fun isSubtypeOfAny(context: AbstractTypeCheckerContext, type: KotlinTypeMarker): Boolean =
|
||||
with(context) {
|
||||
hasNotNullSupertype(type.lowerBoundIfFlexible(), SupertypesPolicy.LowerIfFlexible)
|
||||
}
|
||||
|
||||
private fun AbstractTypeCheckerContext.runIsPossibleSubtype(subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean {
|
||||
if (AbstractTypeChecker.RUN_SLOW_ASSERTIONS) {
|
||||
// it makes for case String? & Any <: String
|
||||
assert(subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || subType.isAllowedTypeVariable) {
|
||||
"Not singleClassifierType and not intersection subType: $subType"
|
||||
}
|
||||
assert(superType.isSingleClassifierType() || superType.isAllowedTypeVariable) {
|
||||
"Not singleClassifierType superType: $superType"
|
||||
}
|
||||
}
|
||||
|
||||
// superType is actually nullable
|
||||
if (superType.isMarkedNullable()) return true
|
||||
|
||||
// i.e. subType is definitely not null
|
||||
if (subType.isDefinitelyNotNullType()) return true
|
||||
|
||||
// i.e. subType is captured type, projection of which is marked not-null
|
||||
if (subType is CapturedTypeMarker && subType.isProjectionNotNull()) return true
|
||||
|
||||
// i.e. subType is not-nullable
|
||||
if (hasNotNullSupertype(subType, SupertypesPolicy.LowerIfFlexible)) return true
|
||||
|
||||
// i.e. subType hasn't not-null supertype and isn't definitely not-null, but superType is definitely not-null
|
||||
if (superType.isDefinitelyNotNullType()) return false
|
||||
|
||||
// i.e subType hasn't not-null supertype, but superType has
|
||||
if (hasNotNullSupertype(superType, SupertypesPolicy.UpperIfFlexible)) return false
|
||||
|
||||
// both superType and subType hasn't not-null supertype and are not definitely not null.
|
||||
|
||||
/**
|
||||
* If we still don't know, it means, that superType is not classType, for example -- type parameter.
|
||||
*
|
||||
* For captured types with lower bound this function can give to you false result. Example:
|
||||
* class A<T>, A<in Number> => \exist Q : Number <: Q. A<Q>
|
||||
* isPossibleSubtype(Number, Q) = false.
|
||||
* Such cases should be taken in to account in [NewKotlinTypeChecker.isSubtypeOf] (same for intersection types)
|
||||
*/
|
||||
|
||||
// classType cannot has special type in supertype list
|
||||
if (subType.isClassType()) return false
|
||||
|
||||
return hasPathByNotMarkedNullableNodes(subType, superType.typeConstructor())
|
||||
}
|
||||
|
||||
fun AbstractTypeCheckerContext.hasNotNullSupertype(type: SimpleTypeMarker, supertypesPolicy: SupertypesPolicy) =
|
||||
anySupertype(type, {
|
||||
(it.isClassType() && !it.isMarkedNullable()) || it.isDefinitelyNotNullType()
|
||||
}) {
|
||||
if (it.isMarkedNullable()) SupertypesPolicy.None else supertypesPolicy
|
||||
}
|
||||
|
||||
fun TypeCheckerProviderContext.hasPathByNotMarkedNullableNodes(start: SimpleTypeMarker, end: TypeConstructorMarker) =
|
||||
newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true)
|
||||
.hasPathByNotMarkedNullableNodes(start, end)
|
||||
|
||||
fun AbstractTypeCheckerContext.hasPathByNotMarkedNullableNodes(start: SimpleTypeMarker, end: TypeConstructorMarker) =
|
||||
anySupertype(
|
||||
start,
|
||||
{ isApplicableAsEndNode(it, end) },
|
||||
{ if (it.isMarkedNullable()) SupertypesPolicy.None else SupertypesPolicy.LowerIfFlexible }
|
||||
)
|
||||
|
||||
private fun AbstractTypeCheckerContext.isApplicableAsEndNode(type: SimpleTypeMarker, end: TypeConstructorMarker): Boolean {
|
||||
if (type.isNothing()) return true
|
||||
if (type.isMarkedNullable()) return false
|
||||
|
||||
if (isStubTypeEqualsToAnything && type.isStubType()) return true
|
||||
|
||||
return isEqualTypeConstructors(type.typeConstructor(), end)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object AbstractFlexibilityChecker {
|
||||
fun TypeSystemCommonSuperTypesContext.hasDifferentFlexibilityAtDepth(types: Collection<KotlinTypeMarker>): Boolean {
|
||||
if (types.isEmpty()) return false
|
||||
if (hasDifferentFlexibility(types)) return true
|
||||
|
||||
for (i in 0 until types.first().argumentsCount()) {
|
||||
val typeArgumentForOtherTypes = types.mapNotNull {
|
||||
if (it.argumentsCount() > i && !it.getArgument(i).isStarProjection()) it.getArgument(i).getType() else null
|
||||
}
|
||||
|
||||
if (hasDifferentFlexibilityAtDepth(typeArgumentForOtherTypes)) return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun TypeSystemCommonSuperTypesContext.hasDifferentFlexibility(types: Collection<KotlinTypeMarker>): Boolean {
|
||||
val firstType = types.first()
|
||||
if (types.all { it === firstType }) return false
|
||||
|
||||
return !types.all { it.isFlexible() } && !types.all { !it.isFlexible() }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.types
|
||||
|
||||
enum class Variance(
|
||||
val label: String,
|
||||
val allowsInPosition: Boolean,
|
||||
val allowsOutPosition: Boolean,
|
||||
private val superpositionFactor: Int
|
||||
) {
|
||||
INVARIANT("", true, true, 0),
|
||||
IN_VARIANCE("in", true, false, -1),
|
||||
OUT_VARIANCE("out", false, true, +1);
|
||||
|
||||
fun allowsPosition(position: Variance): Boolean
|
||||
= when (position) {
|
||||
IN_VARIANCE -> allowsInPosition
|
||||
OUT_VARIANCE -> allowsOutPosition
|
||||
INVARIANT -> allowsInPosition && allowsOutPosition
|
||||
}
|
||||
|
||||
fun superpose(other: Variance): Variance {
|
||||
val r = this.superpositionFactor * other.superpositionFactor
|
||||
return when (r) {
|
||||
0 -> INVARIANT
|
||||
-1 -> IN_VARIANCE
|
||||
+1 -> OUT_VARIANCE
|
||||
else -> throw IllegalStateException("Illegal factor: $r")
|
||||
}
|
||||
}
|
||||
|
||||
fun opposite(): Variance {
|
||||
return when (this) {
|
||||
INVARIANT -> INVARIANT
|
||||
IN_VARIANCE -> OUT_VARIANCE
|
||||
OUT_VARIANCE -> IN_VARIANCE
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString() = label
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.types.model
|
||||
|
||||
fun TypeVariableMarker.freshTypeConstructor(c: TypeSystemInferenceExtensionContext) = with(c) { freshTypeConstructor() }
|
||||
fun TypeSubstitutorMarker.safeSubstitute(
|
||||
c: TypeSystemInferenceExtensionContext,
|
||||
type: KotlinTypeMarker
|
||||
) = with(c) { safeSubstitute(type) }
|
||||
|
||||
fun TypeVariableMarker.defaultType(c: TypeSystemInferenceExtensionContext) = with(c) { defaultType() }
|
||||
|
||||
fun KotlinTypeMarker.dependsOnTypeConstructor(c: TypeSystemInferenceExtensionContext, typeConstructors: Set<TypeConstructorMarker>) =
|
||||
with(c) {
|
||||
contains { it.typeConstructor() in typeConstructors }
|
||||
}
|
||||
|
||||
fun KotlinTypeMarker.dependsOnTypeParameters(c: TypeSystemInferenceExtensionContext, typeParameters: Collection<TypeParameterMarker>) =
|
||||
with(c) {
|
||||
val typeConstructors = typeParameters.mapTo(mutableSetOf()) { it.getTypeConstructor() }
|
||||
dependsOnTypeConstructor(c, typeConstructors)
|
||||
}
|
||||
|
||||
fun CapturedTypeMarker.captureStatus(c: TypeSystemInferenceExtensionContext) =
|
||||
with(c) {
|
||||
captureStatus()
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.types.model
|
||||
|
||||
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||
|
||||
interface KotlinTypeMarker
|
||||
interface TypeArgumentMarker
|
||||
interface TypeConstructorMarker
|
||||
interface TypeParameterMarker
|
||||
|
||||
interface SimpleTypeMarker : KotlinTypeMarker
|
||||
interface CapturedTypeMarker : SimpleTypeMarker
|
||||
interface DefinitelyNotNullTypeMarker : SimpleTypeMarker
|
||||
|
||||
interface FlexibleTypeMarker : KotlinTypeMarker
|
||||
interface DynamicTypeMarker : FlexibleTypeMarker
|
||||
interface RawTypeMarker : FlexibleTypeMarker
|
||||
interface StubTypeMarker : SimpleTypeMarker
|
||||
|
||||
interface TypeArgumentListMarker
|
||||
|
||||
interface TypeVariableMarker
|
||||
interface TypeVariableTypeConstructorMarker : TypeConstructorMarker
|
||||
|
||||
interface CapturedTypeConstructorMarker : TypeConstructorMarker
|
||||
|
||||
interface TypeSubstitutorMarker
|
||||
|
||||
|
||||
enum class TypeVariance(val presentation: String) {
|
||||
IN("in"),
|
||||
OUT("out"),
|
||||
INV("");
|
||||
|
||||
override fun toString(): String = presentation
|
||||
}
|
||||
|
||||
|
||||
interface TypeSystemOptimizationContext {
|
||||
/**
|
||||
* @return true is a.arguments == b.arguments, or false if not supported
|
||||
*/
|
||||
fun identicalArguments(a: SimpleTypeMarker, b: SimpleTypeMarker) = false
|
||||
}
|
||||
|
||||
interface TypeSystemBuiltInsContext {
|
||||
fun nullableNothingType(): SimpleTypeMarker
|
||||
fun nullableAnyType(): SimpleTypeMarker
|
||||
fun nothingType(): SimpleTypeMarker
|
||||
fun anyType(): SimpleTypeMarker
|
||||
}
|
||||
|
||||
interface TypeSystemTypeFactoryContext {
|
||||
fun createFlexibleType(lowerBound: SimpleTypeMarker, upperBound: SimpleTypeMarker): KotlinTypeMarker
|
||||
fun createSimpleType(
|
||||
constructor: TypeConstructorMarker,
|
||||
arguments: List<TypeArgumentMarker>,
|
||||
nullable: Boolean,
|
||||
isExtensionFunction: Boolean = false
|
||||
): SimpleTypeMarker
|
||||
|
||||
fun createTypeArgument(type: KotlinTypeMarker, variance: TypeVariance): TypeArgumentMarker
|
||||
fun createStarProjection(typeParameter: TypeParameterMarker): TypeArgumentMarker
|
||||
|
||||
fun createErrorTypeWithCustomConstructor(debugName: String, constructor: TypeConstructorMarker): KotlinTypeMarker
|
||||
}
|
||||
|
||||
|
||||
interface TypeCheckerProviderContext {
|
||||
fun newBaseTypeCheckerContext(
|
||||
errorTypesEqualToAnything: Boolean,
|
||||
stubTypesEqualToAnything: Boolean
|
||||
): AbstractTypeCheckerContext
|
||||
}
|
||||
|
||||
interface TypeSystemCommonSuperTypesContext : TypeSystemContext, TypeSystemTypeFactoryContext, TypeCheckerProviderContext {
|
||||
|
||||
fun KotlinTypeMarker.anySuperTypeConstructor(predicate: (TypeConstructorMarker) -> Boolean) =
|
||||
newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true)
|
||||
.anySupertype(
|
||||
lowerBoundIfFlexible(),
|
||||
{ predicate(it.typeConstructor()) },
|
||||
{ AbstractTypeCheckerContext.SupertypesPolicy.LowerIfFlexible }
|
||||
)
|
||||
|
||||
fun KotlinTypeMarker.canHaveUndefinedNullability(): Boolean
|
||||
|
||||
fun SimpleTypeMarker.isExtensionFunction(): Boolean
|
||||
|
||||
fun SimpleTypeMarker.typeDepth(): Int
|
||||
|
||||
fun KotlinTypeMarker.typeDepth(): Int = when (this) {
|
||||
is SimpleTypeMarker -> typeDepth()
|
||||
is FlexibleTypeMarker -> maxOf(lowerBound().typeDepth(), upperBound().typeDepth())
|
||||
else -> error("Type should be simple or flexible: $this")
|
||||
}
|
||||
|
||||
fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List<SimpleTypeMarker>): SimpleTypeMarker?
|
||||
|
||||
/*
|
||||
* Converts error type constructor to error type
|
||||
* Used only in FIR
|
||||
*/
|
||||
fun TypeConstructorMarker.toErrorType(): SimpleTypeMarker
|
||||
}
|
||||
|
||||
// This interface is only used to declare that implementing class is supposed to be used as a TypeSystemInferenceExtensionContext component
|
||||
// Otherwise clash happens during DI container initialization: there are a lot of components that extend TypeSystemInferenceExtensionContext
|
||||
// but they only has it among supertypes to bring additional receiver into their scopes, i.e. they are not intended to be used as
|
||||
// component implementation for TypeSystemInferenceExtensionContext
|
||||
interface TypeSystemInferenceExtensionContextDelegate : TypeSystemInferenceExtensionContext
|
||||
|
||||
interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBuiltInsContext, TypeSystemCommonSuperTypesContext {
|
||||
fun KotlinTypeMarker.contains(predicate: (KotlinTypeMarker) -> Boolean): Boolean
|
||||
|
||||
fun TypeConstructorMarker.isUnitTypeConstructor(): Boolean
|
||||
|
||||
fun TypeConstructorMarker.getApproximatedIntegerLiteralType(): KotlinTypeMarker
|
||||
|
||||
fun TypeConstructorMarker.isCapturedTypeConstructor(): Boolean
|
||||
|
||||
fun Collection<KotlinTypeMarker>.singleBestRepresentative(): KotlinTypeMarker?
|
||||
|
||||
fun KotlinTypeMarker.isUnit(): Boolean
|
||||
|
||||
fun KotlinTypeMarker.isBuiltinFunctionalTypeOrSubtype(): Boolean
|
||||
|
||||
fun KotlinTypeMarker.withNullability(nullable: Boolean): KotlinTypeMarker
|
||||
|
||||
|
||||
fun KotlinTypeMarker.makeDefinitelyNotNullOrNotNull(): KotlinTypeMarker
|
||||
fun SimpleTypeMarker.makeSimpleTypeDefinitelyNotNullOrNotNull(): SimpleTypeMarker
|
||||
|
||||
fun createCapturedType(
|
||||
constructorProjection: TypeArgumentMarker,
|
||||
constructorSupertypes: List<KotlinTypeMarker>,
|
||||
lowerType: KotlinTypeMarker?,
|
||||
captureStatus: CaptureStatus
|
||||
): CapturedTypeMarker
|
||||
|
||||
fun createStubType(typeVariable: TypeVariableMarker): StubTypeMarker
|
||||
|
||||
|
||||
fun KotlinTypeMarker.removeAnnotations(): KotlinTypeMarker
|
||||
fun KotlinTypeMarker.removeExactAnnotation(): KotlinTypeMarker
|
||||
|
||||
fun SimpleTypeMarker.replaceArguments(newArguments: List<TypeArgumentMarker>): SimpleTypeMarker
|
||||
|
||||
fun KotlinTypeMarker.hasExactAnnotation(): Boolean
|
||||
fun KotlinTypeMarker.hasNoInferAnnotation(): Boolean
|
||||
|
||||
fun TypeVariableMarker.freshTypeConstructor(): TypeConstructorMarker
|
||||
|
||||
fun CapturedTypeMarker.typeConstructorProjection(): TypeArgumentMarker
|
||||
fun CapturedTypeMarker.typeParameter(): TypeParameterMarker?
|
||||
fun CapturedTypeMarker.withNotNullProjection(): KotlinTypeMarker
|
||||
|
||||
fun DefinitelyNotNullTypeMarker.original(): SimpleTypeMarker
|
||||
|
||||
fun typeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, KotlinTypeMarker>): TypeSubstitutorMarker
|
||||
fun createEmptySubstitutor(): TypeSubstitutorMarker
|
||||
|
||||
fun TypeSubstitutorMarker.safeSubstitute(type: KotlinTypeMarker): KotlinTypeMarker
|
||||
|
||||
|
||||
fun TypeVariableMarker.defaultType(): SimpleTypeMarker
|
||||
|
||||
fun createTypeWithAlternativeForIntersectionResult(
|
||||
firstCandidate: KotlinTypeMarker,
|
||||
secondCandidate: KotlinTypeMarker
|
||||
): KotlinTypeMarker
|
||||
}
|
||||
|
||||
|
||||
class ArgumentList(initialSize: Int) : ArrayList<TypeArgumentMarker>(initialSize), TypeArgumentListMarker
|
||||
|
||||
|
||||
interface TypeSystemContext : TypeSystemOptimizationContext {
|
||||
fun KotlinTypeMarker.asSimpleType(): SimpleTypeMarker?
|
||||
fun KotlinTypeMarker.asFlexibleType(): FlexibleTypeMarker?
|
||||
|
||||
fun KotlinTypeMarker.isError(): Boolean
|
||||
fun TypeConstructorMarker.isError(): Boolean
|
||||
fun KotlinTypeMarker.isUninferredParameter(): Boolean
|
||||
|
||||
fun FlexibleTypeMarker.asDynamicType(): DynamicTypeMarker?
|
||||
|
||||
fun FlexibleTypeMarker.asRawType(): RawTypeMarker?
|
||||
fun FlexibleTypeMarker.upperBound(): SimpleTypeMarker
|
||||
|
||||
fun FlexibleTypeMarker.lowerBound(): SimpleTypeMarker
|
||||
fun SimpleTypeMarker.asCapturedType(): CapturedTypeMarker?
|
||||
|
||||
fun KotlinTypeMarker.isCapturedType() = asSimpleType()?.asCapturedType() != null
|
||||
|
||||
fun SimpleTypeMarker.asDefinitelyNotNullType(): DefinitelyNotNullTypeMarker?
|
||||
fun SimpleTypeMarker.isMarkedNullable(): Boolean
|
||||
fun SimpleTypeMarker.withNullability(nullable: Boolean): SimpleTypeMarker
|
||||
fun SimpleTypeMarker.typeConstructor(): TypeConstructorMarker
|
||||
|
||||
fun CapturedTypeMarker.typeConstructor(): CapturedTypeConstructorMarker
|
||||
fun CapturedTypeMarker.captureStatus(): CaptureStatus
|
||||
fun CapturedTypeMarker.isProjectionNotNull(): Boolean
|
||||
fun CapturedTypeConstructorMarker.projection(): TypeArgumentMarker
|
||||
|
||||
fun KotlinTypeMarker.argumentsCount(): Int
|
||||
fun KotlinTypeMarker.getArgument(index: Int): TypeArgumentMarker
|
||||
|
||||
fun SimpleTypeMarker.getArgumentOrNull(index: Int): TypeArgumentMarker? {
|
||||
if (index in 0 until argumentsCount()) return getArgument(index)
|
||||
return null
|
||||
}
|
||||
|
||||
fun SimpleTypeMarker.isStubType(): Boolean
|
||||
|
||||
fun KotlinTypeMarker.asTypeArgument(): TypeArgumentMarker
|
||||
|
||||
fun CapturedTypeMarker.lowerType(): KotlinTypeMarker?
|
||||
|
||||
fun TypeArgumentMarker.isStarProjection(): Boolean
|
||||
fun TypeArgumentMarker.getVariance(): TypeVariance
|
||||
fun TypeArgumentMarker.getType(): KotlinTypeMarker
|
||||
|
||||
fun TypeConstructorMarker.parametersCount(): Int
|
||||
fun TypeConstructorMarker.getParameter(index: Int): TypeParameterMarker
|
||||
fun TypeConstructorMarker.supertypes(): Collection<KotlinTypeMarker>
|
||||
fun TypeConstructorMarker.isIntersection(): Boolean
|
||||
fun TypeConstructorMarker.isClassTypeConstructor(): Boolean
|
||||
fun TypeConstructorMarker.isIntegerLiteralTypeConstructor(): Boolean
|
||||
|
||||
fun TypeParameterMarker.getVariance(): TypeVariance
|
||||
fun TypeParameterMarker.upperBoundCount(): Int
|
||||
fun TypeParameterMarker.getUpperBound(index: Int): KotlinTypeMarker
|
||||
fun TypeParameterMarker.getTypeConstructor(): TypeConstructorMarker
|
||||
|
||||
fun isEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean
|
||||
|
||||
fun TypeConstructorMarker.isDenotable(): Boolean
|
||||
|
||||
fun KotlinTypeMarker.lowerBoundIfFlexible(): SimpleTypeMarker = this.asFlexibleType()?.lowerBound() ?: this.asSimpleType()!!
|
||||
fun KotlinTypeMarker.upperBoundIfFlexible(): SimpleTypeMarker = this.asFlexibleType()?.upperBound() ?: this.asSimpleType()!!
|
||||
|
||||
fun KotlinTypeMarker.isFlexible(): Boolean = asFlexibleType() != null
|
||||
|
||||
fun KotlinTypeMarker.isDynamic(): Boolean = asFlexibleType()?.asDynamicType() != null
|
||||
fun KotlinTypeMarker.isCapturedDynamic(): Boolean =
|
||||
asSimpleType()?.asCapturedType()?.typeConstructor()?.projection()?.takeUnless { it.isStarProjection() }
|
||||
?.getType()?.isDynamic() == true
|
||||
|
||||
fun KotlinTypeMarker.isDefinitelyNotNullType(): Boolean = asSimpleType()?.asDefinitelyNotNullType() != null
|
||||
|
||||
fun KotlinTypeMarker.hasFlexibleNullability() =
|
||||
lowerBoundIfFlexible().isMarkedNullable() != upperBoundIfFlexible().isMarkedNullable()
|
||||
|
||||
fun KotlinTypeMarker.typeConstructor(): TypeConstructorMarker =
|
||||
(asSimpleType() ?: lowerBoundIfFlexible()).typeConstructor()
|
||||
|
||||
fun KotlinTypeMarker.isNullableType(): Boolean
|
||||
|
||||
fun KotlinTypeMarker.isNullableAny() = this.typeConstructor().isAnyConstructor() && this.isNullableType()
|
||||
fun KotlinTypeMarker.isNothing() = this.typeConstructor().isNothingConstructor() && !this.isNullableType()
|
||||
fun KotlinTypeMarker.isFlexibleNothing() =
|
||||
this is FlexibleTypeMarker && lowerBound().isNothing() && upperBound().isNullableNothing()
|
||||
|
||||
fun KotlinTypeMarker.isNullableNothing() = this.typeConstructor().isNothingConstructor() && this.isNullableType()
|
||||
|
||||
fun SimpleTypeMarker.isClassType(): Boolean = typeConstructor().isClassTypeConstructor()
|
||||
|
||||
fun SimpleTypeMarker.fastCorrespondingSupertypes(constructor: TypeConstructorMarker): List<SimpleTypeMarker>? = null
|
||||
|
||||
fun SimpleTypeMarker.isIntegerLiteralType(): Boolean = typeConstructor().isIntegerLiteralTypeConstructor()
|
||||
|
||||
fun SimpleTypeMarker.possibleIntegerTypes(): Collection<KotlinTypeMarker>
|
||||
|
||||
fun TypeConstructorMarker.isCommonFinalClassConstructor(): Boolean
|
||||
|
||||
fun captureFromArguments(
|
||||
type: SimpleTypeMarker,
|
||||
status: CaptureStatus
|
||||
): SimpleTypeMarker?
|
||||
|
||||
fun captureFromExpression(type: KotlinTypeMarker): KotlinTypeMarker?
|
||||
|
||||
fun SimpleTypeMarker.asArgumentList(): TypeArgumentListMarker
|
||||
|
||||
operator fun TypeArgumentListMarker.get(index: Int): TypeArgumentMarker {
|
||||
return when (this) {
|
||||
is SimpleTypeMarker -> getArgument(index)
|
||||
is ArgumentList -> get(index)
|
||||
else -> error("unknown type argument list type: $this, ${this::class}")
|
||||
}
|
||||
}
|
||||
|
||||
fun TypeArgumentListMarker.size(): Int {
|
||||
return when (this) {
|
||||
is SimpleTypeMarker -> argumentsCount()
|
||||
is ArgumentList -> size
|
||||
else -> error("unknown type argument list type: $this, ${this::class}")
|
||||
}
|
||||
}
|
||||
|
||||
fun TypeConstructorMarker.isAnyConstructor(): Boolean
|
||||
fun TypeConstructorMarker.isNothingConstructor(): Boolean
|
||||
|
||||
/**
|
||||
*
|
||||
* SingleClassifierType is one of the following types:
|
||||
* - classType
|
||||
* - type for type parameter
|
||||
* - captured type
|
||||
*
|
||||
* Such types can contains error types in our arguments, but type constructor isn't errorTypeConstructor
|
||||
*/
|
||||
fun SimpleTypeMarker.isSingleClassifierType(): Boolean
|
||||
|
||||
fun intersectTypes(types: List<KotlinTypeMarker>): KotlinTypeMarker
|
||||
fun intersectTypes(types: List<SimpleTypeMarker>): SimpleTypeMarker
|
||||
|
||||
fun KotlinTypeMarker.isSimpleType() = asSimpleType() != null
|
||||
|
||||
fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker
|
||||
|
||||
fun SimpleTypeMarker.isPrimitiveType(): Boolean
|
||||
}
|
||||
|
||||
enum class CaptureStatus {
|
||||
FOR_SUBTYPING,
|
||||
FOR_INCORPORATION,
|
||||
FROM_EXPRESSION
|
||||
}
|
||||
|
||||
inline fun TypeArgumentListMarker.all(
|
||||
context: TypeSystemContext,
|
||||
crossinline predicate: (TypeArgumentMarker) -> Boolean
|
||||
): Boolean = with(context) {
|
||||
repeat(size()) { index ->
|
||||
if (!predicate(get(index))) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.types.model
|
||||
|
||||
fun KotlinTypeMarker.typeConstructor(context: TypeSystemContext): TypeConstructorMarker =
|
||||
with(context) { typeConstructor() }
|
||||
|
||||
fun TypeConstructorMarker.isIntegerLiteralTypeConstructor(context: TypeSystemContext): Boolean =
|
||||
with(context) { isIntegerLiteralTypeConstructor() }
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.util
|
||||
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
object OperatorNameConventions {
|
||||
@JvmField val GET_VALUE = Name.identifier("getValue")
|
||||
@JvmField val SET_VALUE = Name.identifier("setValue")
|
||||
@JvmField val PROVIDE_DELEGATE = Name.identifier("provideDelegate")
|
||||
|
||||
@JvmField val EQUALS = Name.identifier("equals")
|
||||
@JvmField val COMPARE_TO = Name.identifier("compareTo")
|
||||
@JvmField val CONTAINS = Name.identifier("contains")
|
||||
@JvmField val INVOKE = Name.identifier("invoke")
|
||||
@JvmField val ITERATOR = Name.identifier("iterator")
|
||||
@JvmField val GET = Name.identifier("get")
|
||||
@JvmField val SET = Name.identifier("set")
|
||||
@JvmField val NEXT = Name.identifier("next")
|
||||
@JvmField val HAS_NEXT = Name.identifier("hasNext")
|
||||
|
||||
@JvmField val COMPONENT_REGEX = Regex("component\\d+")
|
||||
|
||||
@JvmField val AND = Name.identifier("and")
|
||||
@JvmField val OR = Name.identifier("or")
|
||||
|
||||
@JvmField val INC = Name.identifier("inc")
|
||||
@JvmField val DEC = Name.identifier("dec")
|
||||
@JvmField val PLUS = Name.identifier("plus")
|
||||
@JvmField val MINUS = Name.identifier("minus")
|
||||
@JvmField val NOT = Name.identifier("not")
|
||||
|
||||
@JvmField val UNARY_MINUS = Name.identifier("unaryMinus")
|
||||
@JvmField val UNARY_PLUS = Name.identifier("unaryPlus")
|
||||
|
||||
@JvmField val TIMES = Name.identifier("times")
|
||||
@JvmField val DIV = Name.identifier("div")
|
||||
@JvmField val MOD = Name.identifier("mod")
|
||||
@JvmField val REM = Name.identifier("rem")
|
||||
@JvmField val RANGE_TO = Name.identifier("rangeTo")
|
||||
|
||||
@JvmField val TIMES_ASSIGN = Name.identifier("timesAssign")
|
||||
@JvmField val DIV_ASSIGN = Name.identifier("divAssign")
|
||||
@JvmField val MOD_ASSIGN = Name.identifier("modAssign")
|
||||
@JvmField val REM_ASSIGN = Name.identifier("remAssign")
|
||||
@JvmField val PLUS_ASSIGN = Name.identifier("plusAssign")
|
||||
@JvmField val MINUS_ASSIGN = Name.identifier("minusAssign")
|
||||
|
||||
// If you add new unary, binary or assignment operators, add it to OperatorConventions as well
|
||||
|
||||
@JvmField
|
||||
val UNARY_OPERATION_NAMES = setOf(INC, DEC, UNARY_PLUS, UNARY_MINUS, NOT)
|
||||
|
||||
@JvmField
|
||||
val SIMPLE_UNARY_OPERATION_NAMES = setOf(UNARY_PLUS, UNARY_MINUS, NOT)
|
||||
|
||||
@JvmField
|
||||
val BINARY_OPERATION_NAMES = setOf(TIMES, PLUS, MINUS, DIV, MOD, REM, RANGE_TO)
|
||||
|
||||
@JvmField
|
||||
val ASSIGNMENT_OPERATIONS = setOf(TIMES_ASSIGN, DIV_ASSIGN, MOD_ASSIGN, REM_ASSIGN, PLUS_ASSIGN, MINUS_ASSIGN)
|
||||
|
||||
@JvmField
|
||||
val DELEGATED_PROPERTY_OPERATORS = setOf(GET_VALUE, SET_VALUE, PROVIDE_DELEGATE)
|
||||
}
|
||||
Reference in New Issue
Block a user