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?)
|
fun isEffectivelyPublic(classAccess: AccessFlags, classVisibility: ClassVisibility?)
|
||||||
= access.isPublic && !(access.isProtected && classAccess.isFinal)
|
= 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
|
val signature: String
|
||||||
}
|
}
|
||||||
@@ -65,9 +68,15 @@ data class FieldBinarySignature(
|
|||||||
override val signature: String
|
override val signature: String
|
||||||
get() = "${access.getModifierString()} field $name $desc"
|
get() = "${access.getModifierString()} field $name $desc"
|
||||||
|
|
||||||
override fun isEffectivelyPublic(classAccess: AccessFlags, classVisibility: ClassVisibility?)
|
override fun findMemberVisibility(classVisibility: ClassVisibility?): MemberVisibility? {
|
||||||
= super.isEffectivelyPublic(classAccess, classVisibility)
|
val fieldVisibility = super.findMemberVisibility(classVisibility) ?: return null
|
||||||
// TODO: lateinit exposed field
|
|
||||||
|
// 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
|
import java.io.File
|
||||||
|
|
||||||
data class ClassVisibility(val name: String, val visibility: String?, val members: Map<MemberSignature, MemberVisibility>)
|
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)
|
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")
|
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 ClassVisibility.isPublic(isInlineExposed: Boolean) = isPublic(visibility, isInlineExposed)
|
||||||
fun MemberVisibility.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> {
|
fun readKotlinVisibilities(declarationFile: File): Map<String, ClassVisibility> {
|
||||||
val result = mutableListOf<ClassVisibility>()
|
val result = mutableListOf<ClassVisibility>()
|
||||||
@@ -27,8 +38,9 @@ fun readKotlinVisibilities(declarationFile: File): Map<String, ClassVisibility>
|
|||||||
with(it.asJsonObject) {
|
with(it.asJsonObject) {
|
||||||
val name = getAsJsonPrimitive("name").asString
|
val name = getAsJsonPrimitive("name").asString
|
||||||
val desc = getAsJsonPrimitive("desc").asString
|
val desc = getAsJsonPrimitive("desc").asString
|
||||||
|
val declaration = getAsJsonPrimitive("declaration")?.asString
|
||||||
val visibility = getAsJsonPrimitive("visibility")?.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 })
|
ClassVisibility(name, visibility, members.associateByTo(hashMapOf()) { it.member })
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
public final class cases/special/ClassWithLateInitMembers
|
public final class cases/special/ClassWithLateInitMembers
|
||||||
public field publicLateInitWithInternalSet Ljava/lang/String;
|
|
||||||
public final fun getPublicLateInitWithInternalSet ()Ljava/lang/String;
|
public final fun getPublicLateInitWithInternalSet ()Ljava/lang/String;
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user