[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) { class KlibPrinter(out: Appendable) {
val printer = Printer(out, 1, " ") 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 val DeclarationDescriptorWithVisibility.isPublicOrProtected: Boolean
get() = visibility == Visibilities.PUBLIC || visibility == Visibilities.PROTECTED get() = visibility == Visibilities.PUBLIC || visibility == Visibilities.PROTECTED
@@ -64,6 +49,27 @@ class KlibPrinter(out: Appendable) {
println() 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) { fun print(module: ModuleDescriptor) {
module.accept(PrinterVisitor(), Unit) module.accept(PrinterVisitor(), Unit)
} }
@@ -89,7 +95,7 @@ class KlibPrinter(out: Appendable) {
override fun visitClassDescriptor(descriptor: ClassDescriptor, data: Unit) { override fun visitClassDescriptor(descriptor: ClassDescriptor, data: Unit) {
val children = descriptor.unsubstitutedMemberScope.getContributedDescriptors().filter { it.shouldBePrinted } val children = descriptor.unsubstitutedMemberScope.getContributedDescriptors().filter { it.shouldBePrinted }
val constructors = descriptor.constructors.filter { !it.isPrimary && 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()) { if (children.isNotEmpty() || constructors.isNotEmpty()) {
printer.printBody(header) { printer.printBody(header) {
constructors.forEach { it.accept(this, data) } constructors.forEach { it.accept(this, data) }
@@ -102,15 +108,36 @@ class KlibPrinter(out: Appendable) {
} }
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Unit) { override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Unit) {
printer.println(renderer.render(descriptor)) printer.println(descriptor.render())
} }
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Unit) { override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Unit) {
printer.println(renderer.render(descriptor)) printer.println(descriptor.render())
} }
override fun visitConstructorDescriptor(constructorDescriptor: ConstructorDescriptor, data: Unit) { override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, data: Unit) {
printer.println(renderer.render(constructorDescriptor)) 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) { fun contents(output: Appendable = out) {
val reader = LibraryReaderImpl(libraryInRepoOrCurrentDir(repository, name), currentAbiVersion) val reader = LibraryReaderImpl(libraryInRepoOrCurrentDir(repository, name), currentAbiVersion)
// TODO: Should the klib tool have arguments like compilerVersion or apiVersion? val versionSpec = LanguageVersionSettingsImpl(currentLanguageVersion, currentApiVersion)
val versionSpec = LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE)
val module = reader.moduleDescriptor(versionSpec) val module = reader.moduleDescriptor(versionSpec)
val defaultModules = mutableListOf<ModuleDescriptorImpl>() val defaultModules = mutableListOf<ModuleDescriptorImpl>()
if (!module.isStdlib()) { if (!module.isStdlib()) {
@@ -169,6 +168,8 @@ class Library(val name: String, val requestedRepository: String?, val target: St
// TODO: need to do something here. // TODO: need to do something here.
val currentAbiVersion = 1 val currentAbiVersion = 1
val currentLanguageVersion = LanguageVersion.LATEST_STABLE
val currentApiVersion = ApiVersion.LATEST_STABLE
fun libraryInRepo(repository: File, name: String): File { fun libraryInRepo(repository: File, name: String): File {
val resolver = KonanLibrarySearchPathResolver( val resolver = KonanLibrarySearchPathResolver(
@@ -26,10 +26,13 @@ class ContentsTest {
private fun testLibrary(name: String) = LIBRARY_DIRECTORY.resolve("$name.klib").toFile().absolutePath 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 output = StringBuilder()
val lib = Library(library, null, "host") val lib = Library(library, null, "host")
lib.contents(output) lib.contents(output)
if (printOutput) {
println(output.trim().toString())
}
assertEquals(expected(), output.trim().toString(), "klib contents test failed for library: $library") 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) inline fun <reified T> t4(x: T)
fun <T : Number> t5(x: T) fun <T : Number> t5(x: T)
fun Foo.e() fun Foo.e()
final annotation class A constructor() : Annotation annotation class A constructor() : Annotation
final annotation class B constructor() : Annotation annotation class B constructor() : Annotation
final class Foo constructor() class Foo constructor()
} }
""".trimIndent() """.trimIndent()
} }
@@ -70,11 +73,11 @@ class ContentsTest {
fun constructors() = klibContents(testLibrary("Constructors")) { fun constructors() = klibContents(testLibrary("Constructors")) {
""" """
package <root> { package <root> {
final annotation class A constructor() : Annotation annotation class A constructor() : Annotation
final class Bar @A constructor(x: Int) class Bar @A constructor(x: Int)
final class Baz private constructor(x: Int) class Baz private constructor(x: Int)
final class Foo constructor(x: Int) { class Foo constructor(x: Int) {
constructor() constructor()
constructor(x: Double) constructor(x: Double)
constructor(x: Double, y: Int) constructor(x: Double, y: Int)
@@ -82,9 +85,9 @@ class ContentsTest {
@A constructor(x: Foo) @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()
constructor(x: Double) constructor(x: Double)
constructor(x: Double, y: Int) constructor(x: Double, y: Int)
@@ -102,25 +105,25 @@ class ContentsTest {
package <root> { package <root> {
object A { object A {
final fun a() fun a()
} }
final class B constructor() { class B constructor() {
object C { object C {
final fun c() fun c()
} }
companion object { companion object {
final fun b() fun b()
} }
} }
final class D constructor() { class D constructor() {
companion object E { companion object E {
final fun e() fun e()
} }
} }
@@ -134,54 +137,54 @@ class ContentsTest {
""" """
package <root> { package <root> {
final class A constructor() { class A constructor() {
final val aVal: Int = 0 val aVal: Int = 0
final var aVar: String var aVar: String
final fun aFun() fun aFun()
final inner class B constructor() { inner class B constructor() {
final val bVal: Int = 0 val bVal: Int = 0
final var bVar: String var bVar: String
final fun bFun() fun bFun()
final inner class C constructor() { inner class C constructor() {
final val cVal: Int = 0 val cVal: Int = 0
final var cVar: String var cVar: String
final fun cFun() fun cFun()
} }
} }
final class E constructor() { class E constructor() {
final val eVal: Int = 0 val eVal: Int = 0
final var eVar: String var eVar: String
final fun eFun() fun eFun()
} }
} }
final data class F constructor(fVal: Int, fVar: String) { data class F constructor(fVal: Int, fVar: String) {
final val fVal: Int val fVal: Int
final var fVar: String var fVar: String
final operator fun component1(): Int operator fun component1(): Int
final operator fun component2(): String operator fun component2(): String
final fun copy(fVal: Int = ..., fVar: String = ...): F fun copy(fVal: Int = ..., fVar: String = ...): F
override fun equals(other: Any?): Boolean override fun equals(other: Any?): Boolean
final fun fFun() fun fFun()
override fun hashCode(): Int override fun hashCode(): Int
override fun toString(): String override fun toString(): String
} }
final class FinalImpl constructor() : OpenImpl { class FinalImpl constructor() : OpenImpl {
override val iVal: Int = 0 override val iVal: Int = 0
override var iVar: String override var iVar: String
override fun iFun() override fun iFun()
} }
interface Interface { interface Interface {
abstract val iVal: Int val iVal: Int
abstract var iVar: String var iVar: String
abstract fun iFun() fun iFun()
} }
open class OpenImpl constructor() : Interface { open class OpenImpl constructor() : Interface {
@@ -194,13 +197,61 @@ class ContentsTest {
""".trimIndent() """.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 @Test
@Ignore // TODO: Do we need to print the overridden method in the C entry? @Ignore // TODO: Do we need to print the overridden method in the C entry?
fun enum() = klibContents(testLibrary("Enum")) { fun enum() = klibContents(testLibrary("Enum")) {
""" """
package <root> { 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 A
enum entry B enum entry B
@@ -208,9 +259,9 @@ class ContentsTest {
override fun enumFun(): Int override fun enumFun(): Int
} }
final val enumVal: Int = 0 val enumVal: Int = 0
final var enumVar: String var enumVar: String
final val x: Int val x: Int
open fun enumFun(): 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() {}
}