All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.autonomousapps.internal.kotlin.kotlinMetadataVisibilities.kt Maven / Gradle / Ivy

There is a newer version: 2.0.2
Show newest version
/*
 * Copyright 2010-2018 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.
 *
 * Copied from https://github.com/JetBrains/kotlin/tree/master/libraries/tools/binary-compatibility-validator
 */

package com.autonomousapps.internal.kotlin

import com.autonomousapps.internal.asm.tree.ClassNode
import kotlinx.metadata.*
import kotlinx.metadata.jvm.*

internal val ClassNode.kotlinMetadata: KotlinClassMetadata?
  get() {
    val metadata = findAnnotation("kotlin/Metadata", false) ?: return null

    @Suppress("UNCHECKED_CAST")
    val header = with(metadata) {
      Metadata(
        kind = get("k") as Int?,
        metadataVersion = (get("mv") as List?)?.toIntArray(),
        data1 = (get("d1") as List?)?.toTypedArray(),
        data2 = (get("d2") as List?)?.toTypedArray(),
        extraString = get("xs") as String?,
        packageName = get("pn") as String?,
        extraInt = get("xi") as Int?
      )
    }
    return KotlinClassMetadata.read(header)
  }


internal fun KotlinClassMetadata?.isFileOrMultipartFacade() =
  this is KotlinClassMetadata.FileFacade || this is KotlinClassMetadata.MultiFileClassFacade

internal fun KotlinClassMetadata?.isSyntheticClass() = this is KotlinClassMetadata.SyntheticClass

internal fun KotlinClassMetadata.toClassVisibility(classNode: ClassNode): ClassVisibility? {
  var flags: Flags? = null
  var _facadeClassName: String? = null
  val members = mutableListOf()

  fun addMember(signature: JvmMemberSignature?, flags: Flags, isReified: Boolean) {
    if (signature != null) {
      members.add(MemberVisibility(signature, flags, isReified))
    }
  }

  val container: KmDeclarationContainer? = when (this) {
    is KotlinClassMetadata.Class ->
      toKmClass().also { klass ->
        flags = klass.flags

        for (constructor in klass.constructors) {
          addMember(constructor.signature, constructor.flags, isReified = false)
        }
      }
    is KotlinClassMetadata.FileFacade ->
      toKmPackage()
    is KotlinClassMetadata.MultiFileClassPart ->
      toKmPackage().also { _facadeClassName = this.facadeClassName }
    else -> null
  }

  if (container != null) {
    fun List.containsReified() = any { Flag.TypeParameter.IS_REIFIED(it.flags) }

    for (function in container.functions) {
      addMember(function.signature, function.flags, function.typeParameters.containsReified())
    }

    for (property in container.properties) {
      val isReified = property.typeParameters.containsReified()
      addMember(property.getterSignature, property.getterFlags, isReified)
      addMember(property.setterSignature, property.setterFlags, isReified)

      val fieldVisibility = when {
        Flag.Property.IS_LATEINIT(property.flags) -> property.setterFlags
        property.getterSignature == null && property.setterSignature == null -> property.flags // JvmField or const case
        else -> flagsOf(Flag.IS_PRIVATE)
      }
      addMember(property.fieldSignature, fieldVisibility, isReified = false)
    }
  }

  return ClassVisibility(classNode.name, flags, members.associateBy { it.member }, _facadeClassName)
}

internal fun ClassNode.toClassVisibility() = kotlinMetadata?.toClassVisibility(this)

internal fun Set.readKotlinVisibilities(): Map =
  mapNotNull { it.toClassVisibility() }
    .associateBy { it.name }
    .apply {
      values.asSequence().filter { it.isCompanion }.forEach {
        val containingClassName = it.name.substringBeforeLast('$')
        getValue(containingClassName).companionVisibilities = it
      }

      values.asSequence().filter { it.facadeClassName != null }.forEach {
        getValue(it.facadeClassName!!).partVisibilities.add(it)
      }
    }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy