Use JVM signatures instead of FQ-names for additional built-ins
This commit is contained in:
@@ -21,7 +21,6 @@ import com.intellij.psi.PsiElement;
|
|||||||
import kotlin.Pair;
|
import kotlin.Pair;
|
||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
import kotlin.collections.CollectionsKt;
|
import kotlin.collections.CollectionsKt;
|
||||||
import kotlin.jvm.functions.Function2;
|
|
||||||
import kotlin.jvm.functions.Function3;
|
import kotlin.jvm.functions.Function3;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -81,7 +80,6 @@ import org.jetbrains.org.objectweb.asm.commons.Method;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isUnit;
|
|
||||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
||||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
|
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
|
||||||
@@ -348,7 +346,7 @@ public class KotlinTypeMapper {
|
|||||||
return Type.VOID_TYPE;
|
return Type.VOID_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUnit(returnType) && !TypeUtils.isNullableType(returnType) && !(descriptor instanceof PropertyGetterDescriptor)) {
|
if (TypeSignatureMappingKt.hasVoidReturnType(descriptor)) {
|
||||||
if (sw != null) {
|
if (sw != null) {
|
||||||
sw.writeAsmType(Type.VOID_TYPE);
|
sw.writeAsmType(Type.VOID_TYPE);
|
||||||
}
|
}
|
||||||
|
|||||||
+104
-41
@@ -24,10 +24,6 @@ import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
|
|||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.load.java.components.JavaResolverCache
|
import org.jetbrains.kotlin.load.java.components.JavaResolverCache
|
||||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor
|
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor
|
||||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassMemberScope
|
|
||||||
import org.jetbrains.kotlin.load.java.lazy.replaceComponents
|
|
||||||
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
|
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||||
@@ -42,10 +38,9 @@ import org.jetbrains.kotlin.serialization.deserialization.AdditionalClassPartsPr
|
|||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||||
import org.jetbrains.kotlin.types.DelegatingType
|
import org.jetbrains.kotlin.types.DelegatingType
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.utils.DFS
|
||||||
import org.jetbrains.kotlin.utils.SmartSet
|
import org.jetbrains.kotlin.utils.SmartSet
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||||
import org.jetbrains.kotlin.utils.sure
|
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -112,11 +107,9 @@ open class BuiltInClassesAreSerializableOnJvm(
|
|||||||
): Collection<SimpleFunctionDescriptor> {
|
): Collection<SimpleFunctionDescriptor> {
|
||||||
val javaAnalogueDescriptor = classDescriptor.getJavaAnalogue() ?: return emptyList()
|
val javaAnalogueDescriptor = classDescriptor.getJavaAnalogue() ?: return emptyList()
|
||||||
|
|
||||||
val platformClassDescriptors = j2kClassMap.mapPlatformClass(javaAnalogueDescriptor.fqNameSafe, DefaultBuiltIns.Instance)
|
val kotlinClassDescriptors = j2kClassMap.mapPlatformClass(javaAnalogueDescriptor.fqNameSafe, DefaultBuiltIns.Instance)
|
||||||
val kotlinMutableClassIfContainer = platformClassDescriptors.lastOrNull() ?: return emptyList()
|
val kotlinMutableClassIfContainer = kotlinClassDescriptors.lastOrNull() ?: return emptyList()
|
||||||
val platformVersions = SmartSet.create(platformClassDescriptors.map { it.fqNameSafe })
|
val kotlinVersions = SmartSet.create(kotlinClassDescriptors.map { it.fqNameSafe })
|
||||||
|
|
||||||
if (javaAnalogueDescriptor.fqNameSafe in IGNORE_BY_DEFAULT_CLASS_FQ_NAMES) return emptyList()
|
|
||||||
|
|
||||||
val isMutable = j2kClassMap.isMutable(classDescriptor)
|
val isMutable = j2kClassMap.isMutable(classDescriptor)
|
||||||
|
|
||||||
@@ -131,18 +124,48 @@ open class BuiltInClassesAreSerializableOnJvm(
|
|||||||
.filter { analogueMember ->
|
.filter { analogueMember ->
|
||||||
if (analogueMember.kind != CallableMemberDescriptor.Kind.DECLARATION) return@filter false
|
if (analogueMember.kind != CallableMemberDescriptor.Kind.DECLARATION) return@filter false
|
||||||
if (!analogueMember.visibility.isPublicAPI) return@filter false
|
if (!analogueMember.visibility.isPublicAPI) return@filter false
|
||||||
|
if (KotlinBuiltIns.isDeprecated(analogueMember)) return@filter false
|
||||||
|
|
||||||
val methodFqName = analogueMember.fqNameSafe
|
if (analogueMember.overriddenDescriptors.any {
|
||||||
|
it.containingDeclaration.fqNameSafe in kotlinVersions
|
||||||
|
}) return@filter false
|
||||||
|
|
||||||
if (methodFqName in BLACK_LIST_METHODS_FQ_NAMES) return@filter false
|
!analogueMember.isInBlackOrMutabilityViolation(isMutable)
|
||||||
if ((methodFqName in MUTABLE_METHODS_FQ_NAMES) xor isMutable) return@filter false
|
|
||||||
|
|
||||||
analogueMember.overriddenDescriptors.none {
|
|
||||||
it.containingDeclaration.fqNameSafe in platformVersions
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun SimpleFunctionDescriptor.isInBlackOrMutabilityViolation(isMutable: Boolean): Boolean {
|
||||||
|
val jvmDescriptor = computeJvmDescriptor()
|
||||||
|
val owner = containingDeclaration as ClassDescriptor
|
||||||
|
if (DFS.ifAny(
|
||||||
|
listOf(owner),
|
||||||
|
{
|
||||||
|
// Search through mapped supertypes to determine that Set.toArray is in blacklist, while we have only
|
||||||
|
// Collection.toArray there explicitly
|
||||||
|
// Note, that we can't find j.u.Collection.toArray within overriddenDescriptors of j.u.Set.toArray
|
||||||
|
it.typeConstructor.supertypes.mapNotNull {
|
||||||
|
(it.constructor.declarationDescriptor?.original as? ClassDescriptor)?.getJavaAnalogue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
javaClassDescriptor ->
|
||||||
|
signature(javaClassDescriptor, jvmDescriptor) in BLACK_LIST_METHOD_SIGNATURES
|
||||||
|
}) return true
|
||||||
|
|
||||||
|
if ((signature(owner, jvmDescriptor) in MUTABLE_METHOD_SIGNATURES) xor isMutable) return true
|
||||||
|
|
||||||
|
return DFS.ifAny<CallableMemberDescriptor>(
|
||||||
|
listOf(this),
|
||||||
|
{ it.original.overriddenDescriptors }
|
||||||
|
) {
|
||||||
|
overridden ->
|
||||||
|
overridden.kind == CallableMemberDescriptor.Kind.DECLARATION &&
|
||||||
|
j2kClassMap.isMutable(overridden.containingDeclaration as ClassDescriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun signature(javaClassDescriptor: ClassDescriptor, jvmDescriptor: String) = javaClassDescriptor.internalName + "." + jvmDescriptor
|
||||||
|
|
||||||
private fun ClassDescriptor.getJavaAnalogue(): LazyJavaClassDescriptor? {
|
private fun ClassDescriptor.getJavaAnalogue(): LazyJavaClassDescriptor? {
|
||||||
// Prevents recursive dependency: memberScope(Any) -> memberScope(Object) -> memberScope(Any)
|
// Prevents recursive dependency: memberScope(Any) -> memberScope(Object) -> memberScope(Any)
|
||||||
// No additional members should be added to Any
|
// No additional members should be added to Any
|
||||||
@@ -205,35 +228,75 @@ open class BuiltInClassesAreSerializableOnJvm(
|
|||||||
return Serializable::class.java.isAssignableFrom(classViaReflection)
|
return Serializable::class.java.isAssignableFrom(classViaReflection)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val IGNORE_BY_DEFAULT_CLASS_FQ_NAMES =
|
private val BLACK_LIST_METHOD_SIGNATURES: Set<String> =
|
||||||
setOf(FqName("java.lang.String")) +
|
|
||||||
JvmPrimitiveType.values().map { it.wrapperFqName }
|
|
||||||
|
|
||||||
private val BLACK_LIST_METHODS_FQ_NAMES =
|
|
||||||
buildPrimitiveValueMethodsSet() +
|
buildPrimitiveValueMethodsSet() +
|
||||||
FqName("java.util.Collection.toArray") +
|
|
||||||
FqName("java.util.List.toArray") +
|
|
||||||
FqName("java.util.Set.toArray") +
|
|
||||||
FqName("java.lang.annotation.Annotation.annotationType")
|
|
||||||
|
|
||||||
private val MUTABLE_METHODS_FQ_NAMES =
|
"java/lang/annotation/Annotation.annotationType()${javaLang("Class").t}" +
|
||||||
inClass("java.util.Collection",
|
|
||||||
"removeIf") +
|
|
||||||
|
|
||||||
inClass("java.util.List",
|
inJavaUtil(
|
||||||
"sort", "replaceAll") +
|
"Collection", "toArray()[Ljava/lang/Object;", "toArray([Ljava/lang/Object;)[Ljava/lang/Object;"
|
||||||
|
) +
|
||||||
|
|
||||||
inClass("java.util.Map",
|
inJavaLang("String",
|
||||||
"compute", "computeIfAbsent", "computeIfPresent", "remove", "merge", "putIfAbsent", "replace", "replaceAll")
|
"codePointAt(I)I", "codePointBefore(I)I", "codePointCount(II)I", "compareToIgnoreCase($stringType)I",
|
||||||
|
"concat($stringType)$stringType", "contains(Ljava/lang/CharSequence;)Z",
|
||||||
|
"contentEquals(Ljava/lang/CharSequence;)Z", "contentEquals(Ljava/lang/StringBuffer;)Z",
|
||||||
|
"endsWith($stringType)Z", "equalsIgnoreCase($stringType)Z", "getBytes()[B", "getBytes(II[BI)V",
|
||||||
|
"getBytes($stringType)[B", "getBytes(Ljava/nio/charset/Charset;)[B", "getChars(II[CI)V",
|
||||||
|
"indexOf(I)I", "indexOf(II)I", "indexOf($stringType)I", "indexOf(${stringType}I)I",
|
||||||
|
"intern()$stringType", "isEmpty()Z", "lastIndexOf(I)I", "lastIndexOf(II)I",
|
||||||
|
"lastIndexOf($stringType)I", "lastIndexOf(${stringType}I)I", "matches($stringType)Z",
|
||||||
|
"offsetByCodePoints(II)I", "regionMatches(I${stringType}II)Z", "regionMatches(ZI${stringType}II)Z",
|
||||||
|
"replaceAll($stringType$stringType)$stringType", "replace(CC)$stringType",
|
||||||
|
"replaceFirst($stringType$stringType)$stringType",
|
||||||
|
"replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)$stringType",
|
||||||
|
"split(${stringType}I)[$stringType", "split($stringType)[$stringType",
|
||||||
|
"startsWith(${stringType}I)Z", "startsWith($stringType)Z", "substring(II)$stringType",
|
||||||
|
"substring(I)$stringType", "toCharArray()[C", "toLowerCase()$stringType",
|
||||||
|
"toLowerCase(Ljava/util/Locale;)$stringType", "toUpperCase()$stringType",
|
||||||
|
"toUpperCase(Ljava/util/Locale;)$stringType", "trim()$stringType") +
|
||||||
|
|
||||||
private fun buildPrimitiveValueMethodsSet() =
|
inJavaLang("Double", "isInfinite()Z", "isNaN()Z") +
|
||||||
JvmPrimitiveType.values().mapTo(LinkedHashSet()) {
|
inJavaLang("Float", "isInfinite()Z", "isNaN()Z") +
|
||||||
it.wrapperFqName.child(Name.identifier(it.javaKeywordName + "Value"))
|
|
||||||
|
inJavaUtil("Collection", "toArray([$objectType)[$objectType", "toArray()[$objectType")
|
||||||
|
|
||||||
|
|
||||||
|
private val MUTABLE_METHOD_SIGNATURES: Set<String> =
|
||||||
|
inJavaUtil("Collection", "removeIf(Ljava/util/function/Predicate;)Z") +
|
||||||
|
|
||||||
|
inJavaUtil("List",
|
||||||
|
"sort(Ljava/util/Comparator;)V", "replaceAll(Ljava/util/function/UnaryOperator;)V") +
|
||||||
|
|
||||||
|
inJavaUtil("Map",
|
||||||
|
"computeIfAbsent(${objectType}Ljava/util/function/Function;)$objectType",
|
||||||
|
"computeIfPresent(${objectType}Ljava/util/function/BiFunction;)$objectType",
|
||||||
|
"compute(${objectType}Ljava/util/function/BiFunction;)$objectType",
|
||||||
|
"merge($objectType${objectType}Ljava/util/function/BiFunction;)$objectType",
|
||||||
|
"putIfAbsent($objectType$objectType)$objectType",
|
||||||
|
"remove($objectType$objectType)Z", "replaceAll(Ljava/util/function/BiFunction;)V",
|
||||||
|
"replace($objectType$objectType)$objectType",
|
||||||
|
"replace($objectType$objectType$objectType)Z")
|
||||||
|
|
||||||
|
private fun buildPrimitiveValueMethodsSet(): Set<String> =
|
||||||
|
JvmPrimitiveType.values().flatMapTo(LinkedHashSet()) {
|
||||||
|
inJavaLang(it.wrapperFqName.shortName().asString(), "${it.javaKeywordName}Value()${it.desc}")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun inClass(classFqName: String, vararg names: String) =
|
|
||||||
names.mapTo(LinkedHashSet()) { FqName(classFqName).child(Name.identifier(it)) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val ClassDescriptor.isAny: Boolean get() = fqNameUnsafe == KotlinBuiltIns.FQ_NAMES.any
|
private val ClassDescriptor.isAny: Boolean get() = fqNameUnsafe == KotlinBuiltIns.FQ_NAMES.any
|
||||||
|
|
||||||
|
private val String.t: String
|
||||||
|
get() = "L$this;"
|
||||||
|
|
||||||
|
private val stringType = javaLang("String").t
|
||||||
|
private val objectType = javaLang("Object").t
|
||||||
|
|
||||||
|
private fun javaLang(name: String) = "java/lang/$name"
|
||||||
|
private fun javaUtil(name: String) = "java/util/$name"
|
||||||
|
|
||||||
|
private fun inJavaLang(name: String, vararg signatures: String) = inClass(javaLang(name), *signatures)
|
||||||
|
private fun inJavaUtil(name: String, vararg signatures: String) = inClass(javaUtil(name), *signatures)
|
||||||
|
|
||||||
|
private fun inClass(internalName: String, vararg signatures: String) = signatures.mapTo(LinkedHashSet()) { internalName + "." + it }
|
||||||
|
|||||||
+120
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.load.kotlin
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
|
fun FunctionDescriptor.computeJvmDescriptor()
|
||||||
|
= StringBuilder().apply {
|
||||||
|
append(if (this@computeJvmDescriptor is ConstructorDescriptor) "<init>" else name.asString())
|
||||||
|
append("(")
|
||||||
|
|
||||||
|
valueParameters.forEach {
|
||||||
|
appendErasedType(it.type)
|
||||||
|
}
|
||||||
|
|
||||||
|
append(")")
|
||||||
|
|
||||||
|
if (hasVoidReturnType(this@computeJvmDescriptor)) {
|
||||||
|
append("V")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
appendErasedType(returnType!!)
|
||||||
|
}
|
||||||
|
}.toString()
|
||||||
|
|
||||||
|
|
||||||
|
val ClassDescriptor.internalName: String
|
||||||
|
get() {
|
||||||
|
return computeInternalName(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun StringBuilder.appendErasedType(type: KotlinType) {
|
||||||
|
append(
|
||||||
|
JvmTypeFactoryImpl.toString(
|
||||||
|
mapType(type, JvmTypeFactoryImpl, TypeMappingMode.DEFAULT, TypeMappingConfigurationImpl, descriptorTypeWriter = null)))
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class JvmType {
|
||||||
|
// null means 'void'
|
||||||
|
class Primitive(val jvmPrimitiveType: JvmPrimitiveType?) : JvmType()
|
||||||
|
class Object(val internalName: String) : JvmType()
|
||||||
|
class Array(val elementType: JvmType) : JvmType()
|
||||||
|
}
|
||||||
|
|
||||||
|
private object JvmTypeFactoryImpl : JvmTypeFactory<JvmType> {
|
||||||
|
override fun boxType(possiblyPrimitiveType: JvmType) =
|
||||||
|
when {
|
||||||
|
possiblyPrimitiveType is JvmType.Primitive && possiblyPrimitiveType.jvmPrimitiveType != null ->
|
||||||
|
createObjectType(
|
||||||
|
JvmClassName.byFqNameWithoutInnerClasses(
|
||||||
|
possiblyPrimitiveType.jvmPrimitiveType.wrapperFqName).internalName)
|
||||||
|
else -> possiblyPrimitiveType
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createFromString(representation: String): JvmType {
|
||||||
|
assert(representation.length > 0) { "empty string as JvmType" }
|
||||||
|
val firstChar = representation[0]
|
||||||
|
|
||||||
|
JvmPrimitiveType.values().firstOrNull { it.desc[0] == firstChar }?.let {
|
||||||
|
return JvmType.Primitive(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
return when (firstChar) {
|
||||||
|
'V' -> JvmType.Primitive(null)
|
||||||
|
'[' -> JvmType.Array(createFromString(representation.substring(1)))
|
||||||
|
else -> {
|
||||||
|
assert(firstChar == 'L' && representation.endsWith(';')) {
|
||||||
|
"Type that is not primitive nor array should be Object, but '$representation' was found"
|
||||||
|
}
|
||||||
|
|
||||||
|
JvmType.Object(representation.substring(1, representation.length - 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createObjectType(internalName: String) = JvmType.Object(internalName)
|
||||||
|
|
||||||
|
override fun toString(type: JvmType): String =
|
||||||
|
when (type) {
|
||||||
|
is JvmType.Array -> "[" + toString(type.elementType)
|
||||||
|
is JvmType.Primitive -> type.jvmPrimitiveType?.desc ?: "V"
|
||||||
|
is JvmType.Object -> "L" + type.internalName + ";"
|
||||||
|
}
|
||||||
|
|
||||||
|
override val javaLangClassType: JvmType
|
||||||
|
get() = createObjectType("java/lang/Class")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private object TypeMappingConfigurationImpl : TypeMappingConfiguration<JvmType> {
|
||||||
|
override fun commonSupertype(types: Collection<KotlinType>): KotlinType {
|
||||||
|
throw AssertionError("There should be no intersection type in existing descriptors, but found: " + types.joinToString())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPredefinedTypeForClass(classDescriptor: ClassDescriptor) = null
|
||||||
|
|
||||||
|
override fun processErrorType(kotlinType: KotlinType, descriptor: ClassDescriptor) {
|
||||||
|
// DO nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-5
@@ -17,10 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.load.kotlin
|
package org.jetbrains.kotlin.load.kotlin
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
|
||||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.load.java.typeEnhancement.hasEnhancedNullability
|
import org.jetbrains.kotlin.load.java.typeEnhancement.hasEnhancedNullability
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
@@ -145,6 +142,13 @@ fun <T : Any> mapType(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun hasVoidReturnType(descriptor: CallableDescriptor): Boolean {
|
||||||
|
if (descriptor is ConstructorDescriptor) return true
|
||||||
|
return KotlinBuiltIns.isUnit(descriptor.returnType!!) && !TypeUtils.isNullableType(descriptor.returnType!!)
|
||||||
|
&& descriptor !is PropertyGetterDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
private fun <T : Any> mapBuiltInType(
|
private fun <T : Any> mapBuiltInType(
|
||||||
type: KotlinType,
|
type: KotlinType,
|
||||||
typeFactory: JvmTypeFactory<T>
|
typeFactory: JvmTypeFactory<T>
|
||||||
@@ -173,7 +177,7 @@ private fun <T : Any> mapBuiltInType(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeInternalName(klass: ClassDescriptor): String {
|
internal fun computeInternalName(klass: ClassDescriptor): String {
|
||||||
val container = klass.containingDeclaration
|
val container = klass.containingDeclaration
|
||||||
|
|
||||||
val name = SpecialNames.safeIdentifier(klass.name).identifier
|
val name = SpecialNames.safeIdentifier(klass.name).identifier
|
||||||
|
|||||||
@@ -156,26 +156,13 @@ fun CallableDescriptor.getOwnerForEffectiveDispatchReceiverParameter(): Declarat
|
|||||||
* @return `true` iff the parameter has a default value, i.e. declares it or inherits by overriding a parameter which has a default value.
|
* @return `true` iff the parameter has a default value, i.e. declares it or inherits by overriding a parameter which has a default value.
|
||||||
*/
|
*/
|
||||||
fun ValueParameterDescriptor.hasDefaultValue(): Boolean {
|
fun ValueParameterDescriptor.hasDefaultValue(): Boolean {
|
||||||
val handler = object : DFS.AbstractNodeHandler<ValueParameterDescriptor, Boolean>() {
|
return DFS.ifAny(
|
||||||
var result = false
|
|
||||||
|
|
||||||
override fun beforeChildren(current: ValueParameterDescriptor): Boolean {
|
|
||||||
result = result || current.declaresDefaultValue()
|
|
||||||
return !result
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun result() = result
|
|
||||||
}
|
|
||||||
|
|
||||||
DFS.dfs(
|
|
||||||
listOf(this),
|
listOf(this),
|
||||||
DFS.Neighbors<ValueParameterDescriptor> { current ->
|
DFS.Neighbors<ValueParameterDescriptor> { current ->
|
||||||
current.overriddenDescriptors.map(ValueParameterDescriptor::getOriginal)
|
current.overriddenDescriptors.map(ValueParameterDescriptor::getOriginal)
|
||||||
},
|
},
|
||||||
handler
|
ValueParameterDescriptor::declaresDefaultValue
|
||||||
)
|
)
|
||||||
|
|
||||||
return handler.result()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Annotated.isRepeatableAnnotation(): Boolean =
|
fun Annotated.isRepeatableAnnotation(): Boolean =
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.utils;
|
package org.jetbrains.kotlin.utils;
|
||||||
|
|
||||||
|
import kotlin.jvm.functions.Function1;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -36,6 +37,30 @@ public class DFS {
|
|||||||
return dfs(nodes, neighbors, new VisitedWithSet<N>(), handler);
|
return dfs(nodes, neighbors, new VisitedWithSet<N>(), handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <N> Boolean ifAny(
|
||||||
|
@NotNull Collection<N> nodes,
|
||||||
|
@NotNull Neighbors<N> neighbors,
|
||||||
|
@NotNull final Function1<N, Boolean> predicate
|
||||||
|
) {
|
||||||
|
final boolean[] result = new boolean[1];
|
||||||
|
|
||||||
|
return dfs(nodes, neighbors, new AbstractNodeHandler<N, Boolean>() {
|
||||||
|
@Override
|
||||||
|
public boolean beforeChildren(N current) {
|
||||||
|
if (predicate.invoke(current)) {
|
||||||
|
result[0] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !result[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean result() {
|
||||||
|
return result[0];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public static <N, R> R dfsFromNode(@NotNull N node, @NotNull Neighbors<N> neighbors, @NotNull Visited<N> visited, @NotNull NodeHandler<N, R> handler) {
|
public static <N, R> R dfsFromNode(@NotNull N node, @NotNull Neighbors<N> neighbors, @NotNull Visited<N> visited, @NotNull NodeHandler<N, R> handler) {
|
||||||
doDfs(node, neighbors, visited, handler);
|
doDfs(node, neighbors, visited, handler);
|
||||||
return handler.result();
|
return handler.result();
|
||||||
|
|||||||
Reference in New Issue
Block a user