Infer lateinit-exposed field effective visibility from its setter visibility.
This commit is contained in:
+13
-4
@@ -37,7 +37,10 @@ interface MemberBinarySignature {
|
||||
|
||||
fun isEffectivelyPublic(classAccess: AccessFlags, classVisibility: ClassVisibility?)
|
||||
= access.isPublic && !(access.isProtected && classAccess.isFinal)
|
||||
&& (classVisibility?.members?.get(MemberSignature(name, desc))?.isPublic(isInlineExposed) ?: true)
|
||||
&& (findMemberVisibility(classVisibility)?.isPublic(isInlineExposed) ?: true)
|
||||
|
||||
fun findMemberVisibility(classVisibility: ClassVisibility?)
|
||||
= classVisibility?.members?.get(MemberSignature(name, desc))
|
||||
|
||||
val signature: String
|
||||
}
|
||||
@@ -65,9 +68,15 @@ data class FieldBinarySignature(
|
||||
override val signature: String
|
||||
get() = "${access.getModifierString()} field $name $desc"
|
||||
|
||||
override fun isEffectivelyPublic(classAccess: AccessFlags, classVisibility: ClassVisibility?)
|
||||
= super.isEffectivelyPublic(classAccess, classVisibility)
|
||||
// TODO: lateinit exposed field
|
||||
override fun findMemberVisibility(classVisibility: ClassVisibility?): MemberVisibility? {
|
||||
val fieldVisibility = super.findMemberVisibility(classVisibility) ?: return null
|
||||
|
||||
// good case for 'satisfying': fieldVisibility.satisfying { it.isLateInit() }?.let { classVisibility?.findSetterForProperty(it) }
|
||||
if (fieldVisibility.isLateInit()) {
|
||||
classVisibility?.findSetterForProperty(fieldVisibility)?.let { return it }
|
||||
}
|
||||
return fieldVisibility
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+14
-2
@@ -5,13 +5,24 @@ import com.google.gson.stream.JsonReader
|
||||
import java.io.File
|
||||
|
||||
data class ClassVisibility(val name: String, val visibility: String?, val members: Map<MemberSignature, MemberVisibility>)
|
||||
data class MemberVisibility(val member: MemberSignature, val visibility: String?)
|
||||
data class MemberVisibility(val member: MemberSignature, val declaration: String?, val visibility: String?)
|
||||
data class MemberSignature(val name: String, val desc: String)
|
||||
|
||||
private fun isPublic(visibility: String?, isInlineExposed: Boolean) = visibility == null || visibility == "public" || visibility == "protected" || (isInlineExposed && visibility == "internal")
|
||||
fun ClassVisibility.isPublic(isInlineExposed: Boolean) = isPublic(visibility, isInlineExposed)
|
||||
fun MemberVisibility.isPublic(isInlineExposed: Boolean) = isPublic(visibility, isInlineExposed)
|
||||
|
||||
fun MemberVisibility.isLateInit() = declaration != null && "lateinit var " in declaration
|
||||
|
||||
private val varValPrefix = Regex("va[lr]\\s+")
|
||||
fun ClassVisibility.findSetterForProperty(property: MemberVisibility): MemberVisibility? {
|
||||
// ad-hoc solution:
|
||||
val declaration = property.declaration ?: return null
|
||||
val match = varValPrefix.find(declaration) ?: return null
|
||||
val name = declaration.substring(match.range.endInclusive + 1).substringBefore(':')
|
||||
val setterName = "<set-$name>"
|
||||
return members.values.find { it.declaration?.contains(setterName) ?: false }
|
||||
}
|
||||
|
||||
fun readKotlinVisibilities(declarationFile: File): Map<String, ClassVisibility> {
|
||||
val result = mutableListOf<ClassVisibility>()
|
||||
@@ -27,8 +38,9 @@ fun readKotlinVisibilities(declarationFile: File): Map<String, ClassVisibility>
|
||||
with(it.asJsonObject) {
|
||||
val name = getAsJsonPrimitive("name").asString
|
||||
val desc = getAsJsonPrimitive("desc").asString
|
||||
val declaration = getAsJsonPrimitive("declaration")?.asString
|
||||
val visibility = getAsJsonPrimitive("visibility")?.asString
|
||||
MemberVisibility(MemberSignature(name, desc), visibility)
|
||||
MemberVisibility(MemberSignature(name, desc), declaration, visibility)
|
||||
}
|
||||
}
|
||||
ClassVisibility(name, visibility, members.associateByTo(hashMapOf()) { it.member })
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
public final class cases/special/ClassWithLateInitMembers
|
||||
public field publicLateInitWithInternalSet Ljava/lang/String;
|
||||
public final fun getPublicLateInitWithInternalSet ()Ljava/lang/String;
|
||||
------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user