Rename :core:descriptors.common to :core:compiler.common

This commit is contained in:
Dmitriy Novozhilov
2020-08-20 14:07:02 +03:00
parent 864cf21f03
commit bc1b6d3588
44 changed files with 11 additions and 11 deletions
+23
View File
@@ -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
}
}
}
@@ -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();
}
@@ -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()
}
@@ -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) {
}
}
}
@@ -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 = "/")
@@ -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())
}
}
}
@@ -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
)
@@ -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
}
@@ -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)
}