[klib] Don't print 'final' modality

This commit is contained in:
Ilya Matveev
2018-02-20 14:38:29 +03:00
committed by ilmat192
parent 5f100c620e
commit ba56d17cec
5 changed files with 176 additions and 69 deletions
@@ -29,21 +29,6 @@ import org.jetbrains.kotlin.utils.Printer
class KlibPrinter(out: Appendable) {
val printer = Printer(out, 1, " ")
val renderer = DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.withOptions {
modifiers = DescriptorRendererModifier.ALL
overrideRenderingPolicy = OverrideRenderingPolicy.RENDER_OVERRIDE
annotationArgumentsRenderingPolicy = AnnotationArgumentsRenderingPolicy.UNLESS_EMPTY
excludedAnnotationClasses += setOf(KotlinBuiltIns.FQ_NAMES.suppress)
classWithPrimaryConstructor = true
renderConstructorKeyword = true
includePropertyConstant = true
unitReturnType = false
withDefinedIn = false
renderDefaultVisibility = false
secondaryConstructorsAsPrimary = false
}
val DeclarationDescriptorWithVisibility.isPublicOrProtected: Boolean
get() = visibility == Visibilities.PUBLIC || visibility == Visibilities.PROTECTED
@@ -64,6 +49,27 @@ class KlibPrinter(out: Appendable) {
println()
}
private fun ClassDescriptor.render(): String {
val renderer = when (modality) {
// Don't render 'final' modality
Modality.FINAL -> Renderers.WITHOUT_MODALITY
else -> Renderers.DEFAULT
}
return renderer.render(this)
}
private fun CallableMemberDescriptor.render(): String {
val containingDeclaration = containingDeclaration
val renderer = when {
// Don't render modality for non-override final methods and interface methods.
containingDeclaration is ClassDescriptor && containingDeclaration.kind == ClassKind.INTERFACE ||
modality == Modality.FINAL && overriddenDescriptors.isEmpty() ->
Renderers.WITHOUT_MODALITY
else -> Renderers.DEFAULT
}
return renderer.render(this)
}
fun print(module: ModuleDescriptor) {
module.accept(PrinterVisitor(), Unit)
}
@@ -89,7 +95,7 @@ class KlibPrinter(out: Appendable) {
override fun visitClassDescriptor(descriptor: ClassDescriptor, data: Unit) {
val children = descriptor.unsubstitutedMemberScope.getContributedDescriptors().filter { it.shouldBePrinted }
val constructors = descriptor.constructors.filter { !it.isPrimary && it.shouldBePrinted }
val header = renderer.render(descriptor)
val header = descriptor.render()
if (children.isNotEmpty() || constructors.isNotEmpty()) {
printer.printBody(header) {
constructors.forEach { it.accept(this, data) }
@@ -102,15 +108,36 @@ class KlibPrinter(out: Appendable) {
}
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Unit) {
printer.println(renderer.render(descriptor))
printer.println(descriptor.render())
}
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Unit) {
printer.println(renderer.render(descriptor))
printer.println(descriptor.render())
}
override fun visitConstructorDescriptor(constructorDescriptor: ConstructorDescriptor, data: Unit) {
printer.println(renderer.render(constructorDescriptor))
override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, data: Unit) {
printer.println(descriptor.render())
}
}
object Renderers {
val DEFAULT = DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.withOptions {
modifiers = DescriptorRendererModifier.ALL
overrideRenderingPolicy = OverrideRenderingPolicy.RENDER_OVERRIDE
annotationArgumentsRenderingPolicy = AnnotationArgumentsRenderingPolicy.UNLESS_EMPTY
excludedAnnotationClasses += setOf(KotlinBuiltIns.FQ_NAMES.suppress)
classWithPrimaryConstructor = true
renderConstructorKeyword = true
includePropertyConstant = true
unitReturnType = false
withDefinedIn = false
renderDefaultVisibility = false
secondaryConstructorsAsPrimary = false
}
val WITHOUT_MODALITY = DEFAULT.withOptions {
modifiers -= DescriptorRendererModifier.MODALITY
}
}
@@ -143,8 +143,7 @@ class Library(val name: String, val requestedRepository: String?, val target: St
fun contents(output: Appendable = out) {
val reader = LibraryReaderImpl(libraryInRepoOrCurrentDir(repository, name), currentAbiVersion)
// TODO: Should the klib tool have arguments like compilerVersion or apiVersion?
val versionSpec = LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE)
val versionSpec = LanguageVersionSettingsImpl(currentLanguageVersion, currentApiVersion)
val module = reader.moduleDescriptor(versionSpec)
val defaultModules = mutableListOf<ModuleDescriptorImpl>()
if (!module.isStdlib()) {
@@ -169,6 +168,8 @@ class Library(val name: String, val requestedRepository: String?, val target: St
// TODO: need to do something here.
val currentAbiVersion = 1
val currentLanguageVersion = LanguageVersion.LATEST_STABLE
val currentApiVersion = ApiVersion.LATEST_STABLE
fun libraryInRepo(repository: File, name: String): File {
val resolver = KonanLibrarySearchPathResolver(
@@ -26,10 +26,13 @@ class ContentsTest {
private fun testLibrary(name: String) = LIBRARY_DIRECTORY.resolve("$name.klib").toFile().absolutePath
private fun klibContents(library: String, expected: () -> String) {
private fun klibContents(library: String, printOutput: Boolean = false, expected: () -> String) {
val output = StringBuilder()
val lib = Library(library, null, "host")
lib.contents(output)
if (printOutput) {
println(output.trim().toString())
}
assertEquals(expected(), output.trim().toString(), "klib contents test failed for library: $library")
}
@@ -59,9 +62,9 @@ class ContentsTest {
inline fun <reified T> t4(x: T)
fun <T : Number> t5(x: T)
fun Foo.e()
final annotation class A constructor() : Annotation
final annotation class B constructor() : Annotation
final class Foo constructor()
annotation class A constructor() : Annotation
annotation class B constructor() : Annotation
class Foo constructor()
}
""".trimIndent()
}
@@ -70,11 +73,11 @@ class ContentsTest {
fun constructors() = klibContents(testLibrary("Constructors")) {
"""
package <root> {
final annotation class A constructor() : Annotation
final class Bar @A constructor(x: Int)
final class Baz private constructor(x: Int)
annotation class A constructor() : Annotation
class Bar @A constructor(x: Int)
class Baz private constructor(x: Int)
final class Foo constructor(x: Int) {
class Foo constructor(x: Int) {
constructor()
constructor(x: Double)
constructor(x: Double, y: Int)
@@ -82,9 +85,9 @@ class ContentsTest {
@A constructor(x: Foo)
}
final class Qux protected constructor(x: Int)
class Qux protected constructor(x: Int)
final class Typed<T> constructor(x: Int) {
class Typed<T> constructor(x: Int) {
constructor()
constructor(x: Double)
constructor(x: Double, y: Int)
@@ -102,25 +105,25 @@ class ContentsTest {
package <root> {
object A {
final fun a()
fun a()
}
final class B constructor() {
class B constructor() {
object C {
final fun c()
fun c()
}
companion object {
final fun b()
fun b()
}
}
final class D constructor() {
class D constructor() {
companion object E {
final fun e()
fun e()
}
}
@@ -134,54 +137,54 @@ class ContentsTest {
"""
package <root> {
final class A constructor() {
final val aVal: Int = 0
final var aVar: String
final fun aFun()
class A constructor() {
val aVal: Int = 0
var aVar: String
fun aFun()
final inner class B constructor() {
final val bVal: Int = 0
final var bVar: String
final fun bFun()
inner class B constructor() {
val bVal: Int = 0
var bVar: String
fun bFun()
final inner class C constructor() {
final val cVal: Int = 0
final var cVar: String
final fun cFun()
inner class C constructor() {
val cVal: Int = 0
var cVar: String
fun cFun()
}
}
final class E constructor() {
final val eVal: Int = 0
final var eVar: String
final fun eFun()
class E constructor() {
val eVal: Int = 0
var eVar: String
fun eFun()
}
}
final data class F constructor(fVal: Int, fVar: String) {
final val fVal: Int
final var fVar: String
final operator fun component1(): Int
final operator fun component2(): String
final fun copy(fVal: Int = ..., fVar: String = ...): F
data class F constructor(fVal: Int, fVar: String) {
val fVal: Int
var fVar: String
operator fun component1(): Int
operator fun component2(): String
fun copy(fVal: Int = ..., fVar: String = ...): F
override fun equals(other: Any?): Boolean
final fun fFun()
fun fFun()
override fun hashCode(): Int
override fun toString(): String
}
final class FinalImpl constructor() : OpenImpl {
class FinalImpl constructor() : OpenImpl {
override val iVal: Int = 0
override var iVar: String
override fun iFun()
}
interface Interface {
abstract val iVal: Int
abstract var iVar: String
abstract fun iFun()
val iVal: Int
var iVar: String
fun iFun()
}
open class OpenImpl constructor() : Interface {
@@ -194,13 +197,61 @@ class ContentsTest {
""".trimIndent()
}
@Test
fun methodModality() = klibContents(testLibrary("MethodModality")) {
"""
package <root> {
abstract class AbstractClass constructor() : Interface {
abstract fun abstractFun()
override fun interfaceFun()
}
class FinalClass constructor() : OpenClass {
override fun openFun1()
final override fun openFun2()
}
interface Interface {
fun interfaceFun()
}
open class OpenClass constructor() : AbstractClass {
override fun abstractFun()
fun finalFun()
open fun openFun1()
open fun openFun2()
}
}
""".trimIndent()
}
@Test
fun functionModifiers() = klibContents(testLibrary("FunctionModifiers")) {
"""
package <root> {
class Foo constructor() {
fun f1()
infix fun f2(x: Int)
suspend fun f3()
tailrec fun f4()
fun f5(vararg x: Int)
operator fun plus(x: Int)
}
}
""".trimIndent()
}
@Test
@Ignore // TODO: Do we need to print the overridden method in the C entry?
fun enum() = klibContents(testLibrary("Enum")) {
"""
package <root> {
final enum class E private constructor(x: Int = ...) : Enum<E> {
enum class E private constructor(x: Int = ...) : Enum<E> {
enum entry A
enum entry B
@@ -208,9 +259,9 @@ class ContentsTest {
override fun enumFun(): Int
}
final val enumVal: Int = 0
final var enumVar: String
final val x: Int
val enumVal: Int = 0
var enumVar: String
val x: Int
open fun enumFun(): Int
}
@@ -0,0 +1,8 @@
class Foo {
fun f1() {}
infix fun f2(x: Int) {}
suspend fun f3() {}
operator fun plus(x: Int) {}
tailrec fun f4() {}
fun f5(vararg x: Int) {}
}
+20
View File
@@ -0,0 +1,20 @@
interface Interface {
fun interfaceFun()
}
abstract class AbstractClass: Interface {
override fun interfaceFun() {}
abstract fun abstractFun()
}
open class OpenClass: AbstractClass() {
override fun abstractFun() {}
open fun openFun1() {}
open fun openFun2() {}
fun finalFun() {}
}
class FinalClass: OpenClass() {
override fun openFun1() {}
final override fun openFun2() {}
}