mirror of
https://github.com/jlengrand/ktor.git
synced 2026-03-10 08:31:20 +00:00
Update binary compatibility validator
This commit is contained in:
committed by
Leonid Stashevsky
parent
69f60e0755
commit
e0bb31f6c7
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
|
||||
*/
|
||||
|
||||
kotlin.sourceSets.jvmMain.dependencies {
|
||||
api "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
|
||||
api project(":ktor-utils")
|
||||
api 'org.ow2.asm:asm-debug-all:5.0.4'
|
||||
api 'com.google.code.gson:gson:2.6.2'
|
||||
}
|
||||
|
||||
kotlin.sourceSets.jvmTest.dependencies {
|
||||
api "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
|
||||
api "junit:junit:4.12"
|
||||
}
|
||||
|
||||
apply from: rootProject.file('gradle/compatibility.gradle')
|
||||
|
||||
def binaryCompatibilityModules = project.ext.buildList() as List<ProjectDependency>
|
||||
def artifactNames = binaryCompatibilityModules.collect { it.dependencyProject.name }
|
||||
def modules = binaryCompatibilityModules.collect { it.dependencyProject.projectDir }
|
||||
|
||||
jvmTest {
|
||||
dependsOn configurations.binaryCompatibility
|
||||
|
||||
systemProperty 'validator.input.modules', modules.join(File.pathSeparator)
|
||||
systemProperty 'validator.input.artifactNames', artifactNames.join(File.pathSeparator)
|
||||
systemProperty 'overwrite.output', project.properties['overwrite.output']
|
||||
jvmArgs '-ea'
|
||||
}
|
||||
|
||||
binaryCompatibilityModules.each {
|
||||
jvmTest.dependsOn(it.dependencyProject.getTasksByName("jvmJar", true))
|
||||
}
|
||||
41
binary-compatibility-validator/build.gradle.kts
Normal file
41
binary-compatibility-validator/build.gradle.kts
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
|
||||
*/
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
|
||||
val binaryCompatibility = configurations.create("binaryCompatibility").apply {
|
||||
usesPlatformOf(kotlin.jvm())
|
||||
}
|
||||
|
||||
kotlin.sourceSets {
|
||||
val jvmMain by getting {
|
||||
dependencies {
|
||||
api("org.jetbrains.kotlin:kotlin-stdlib:1.3.21")
|
||||
api("org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.0.5")
|
||||
api("org.ow2.asm:asm:6.0")
|
||||
api("org.ow2.asm:asm-tree:6.0")
|
||||
}
|
||||
}
|
||||
|
||||
val jvmTest by getting {
|
||||
dependencies {
|
||||
api("org.jetbrains.kotlin:kotlin-test-junit:1.3.21")
|
||||
api("junit:junit:4.12")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply(from = rootProject.file("gradle/compatibility.gradle"))
|
||||
|
||||
tasks.getByName<Test>("jvmTest") {
|
||||
dependsOn(binaryCompatibility)
|
||||
|
||||
val projectDependencies = binaryCompatibility.allDependencies.withType<ProjectDependency>()
|
||||
val artifacts = projectDependencies.joinToString(File.pathSeparator) { it.dependencyProject.name }
|
||||
val modules = projectDependencies.joinToString(File.pathSeparator) { it.dependencyProject.projectDir.path }
|
||||
|
||||
systemProperty("validator.input.artifactNames", artifacts)
|
||||
systemProperty("validator.input.modules", modules)
|
||||
systemProperty("overwrite.output", project.properties["overwrite.output"].toString())
|
||||
jvmArgs("-ea")
|
||||
}
|
||||
@@ -1,74 +1,63 @@
|
||||
/*
|
||||
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlinx.coroutines.tools
|
||||
package io.ktor.validator
|
||||
|
||||
import kotlinx.metadata.jvm.*
|
||||
import org.objectweb.asm.*
|
||||
import org.objectweb.asm.tree.*
|
||||
import java.io.*
|
||||
import java.util.jar.*
|
||||
|
||||
fun JarFile.classEntries() = entries().asSequence().filter {
|
||||
fun main(args: Array<String>) {
|
||||
val src = args[0]
|
||||
println(src)
|
||||
println("------------------\n");
|
||||
getBinaryAPI(JarFile(src)).filterOutNonPublic().dump()
|
||||
}
|
||||
|
||||
|
||||
fun JarFile.classEntries() = Sequence { entries().iterator() }.filter {
|
||||
!it.isDirectory && it.name.endsWith(".class") && !it.name.startsWith("META-INF/")
|
||||
}
|
||||
|
||||
fun getBinaryAPI(jar: JarFile, visibilityMap: Map<String, ClassVisibility>): List<ClassBinarySignature> =
|
||||
getBinaryAPI(jar.classEntries().map { entry -> jar.getInputStream(entry) }, visibilityMap)
|
||||
fun getBinaryAPI(jar: JarFile, visibilityFilter: (String) -> Boolean = { true }): List<ClassBinarySignature> =
|
||||
getBinaryAPI(jar.classEntries().map { entry -> jar.getInputStream(entry) }, visibilityFilter)
|
||||
|
||||
fun getBinaryAPI(
|
||||
classStreams: Sequence<InputStream>,
|
||||
visibilityMap: Map<String, ClassVisibility>
|
||||
): List<ClassBinarySignature> =
|
||||
classStreams.map {
|
||||
it.use { stream ->
|
||||
fun getBinaryAPI(classStreams: Sequence<InputStream>, visibilityFilter: (String) -> Boolean = { true }): List<ClassBinarySignature> {
|
||||
val classNodes = classStreams.map { it.use { stream ->
|
||||
val classNode = ClassNode()
|
||||
ClassReader(stream).accept(classNode, ClassReader.SKIP_CODE)
|
||||
classNode
|
||||
}
|
||||
}.map {
|
||||
with(it) {
|
||||
val classVisibility = visibilityMap[name]
|
||||
val classAccess = AccessFlags(effectiveAccess and Opcodes.ACC_STATIC.inv())
|
||||
val supertypes = listOf(superName) - "java/lang/Object" + interfaces.sorted()
|
||||
}}
|
||||
|
||||
val memberSignatures = (
|
||||
fields.map {
|
||||
with(it) {
|
||||
FieldBinarySignature(
|
||||
name,
|
||||
desc,
|
||||
isPublishedApi(),
|
||||
AccessFlags(access)
|
||||
)
|
||||
}
|
||||
} +
|
||||
methods.map {
|
||||
with(it) {
|
||||
MethodBinarySignature(
|
||||
name,
|
||||
desc,
|
||||
isPublishedApi(),
|
||||
AccessFlags(access)
|
||||
)
|
||||
}
|
||||
}
|
||||
val visibilityMapNew = classNodes.readKotlinVisibilities().filterKeys(visibilityFilter)
|
||||
|
||||
return classNodes
|
||||
.map { with(it) {
|
||||
val metadata = kotlinMetadata
|
||||
val mVisibility = visibilityMapNew[name]
|
||||
val classAccess = AccessFlags(effectiveAccess and Opcodes.ACC_STATIC.inv())
|
||||
|
||||
val supertypes = listOf(superName) - "java/lang/Object" + interfaces.sorted()
|
||||
|
||||
val memberSignatures = (
|
||||
fields.map { with(it) { FieldBinarySignature(JvmFieldSignature(name, desc), isPublishedApi(), AccessFlags(access)) } } +
|
||||
methods.map { with(it) { MethodBinarySignature(JvmMethodSignature(name, desc), isPublishedApi(), AccessFlags(access)) } }
|
||||
).filter {
|
||||
it.isEffectivelyPublic(classAccess, classVisibility)
|
||||
}
|
||||
it.isEffectivelyPublic(classAccess, mVisibility)
|
||||
}
|
||||
|
||||
ClassBinarySignature(name, superName, outerClassName, supertypes, memberSignatures, classAccess,
|
||||
isEffectivelyPublic(mVisibility), metadata.isFileOrMultipartFacade() || isDefaultImpls(metadata)
|
||||
)
|
||||
}}
|
||||
.asIterable()
|
||||
.sortedBy { it.name }
|
||||
}
|
||||
|
||||
ClassBinarySignature(
|
||||
name,
|
||||
superName,
|
||||
outerClassName,
|
||||
supertypes,
|
||||
memberSignatures,
|
||||
classAccess,
|
||||
isEffectivelyPublic(classVisibility),
|
||||
isFileOrMultipartFacade() || isDefaultImpls()
|
||||
)
|
||||
}
|
||||
}.asIterable().sortedBy { it.name }
|
||||
|
||||
|
||||
fun List<ClassBinarySignature>.filterOutNonPublic(nonPublicPackages: List<String> = emptyList()): List<ClassBinarySignature> {
|
||||
@@ -80,10 +69,10 @@ fun List<ClassBinarySignature>.filterOutNonPublic(nonPublicPackages: List<String
|
||||
|
||||
fun ClassBinarySignature.isPublicAndAccessible(): Boolean =
|
||||
isEffectivelyPublic &&
|
||||
(outerName == null || classByName[outerName]?.let { outerClass ->
|
||||
!(this.access.isProtected && outerClass.access.isFinal)
|
||||
&& outerClass.isPublicAndAccessible()
|
||||
} ?: true)
|
||||
(outerName == null || classByName[outerName]?.let { outerClass ->
|
||||
!(this.access.isProtected && outerClass.access.isFinal)
|
||||
&& outerClass.isPublicAndAccessible()
|
||||
} ?: true)
|
||||
|
||||
fun supertypes(superName: String) = generateSequence({ classByName[superName] }, { classByName[it.superName] })
|
||||
|
||||
@@ -93,28 +82,22 @@ fun List<ClassBinarySignature>.filterOutNonPublic(nonPublicPackages: List<String
|
||||
if (nonPublicSupertypes.isEmpty())
|
||||
return this
|
||||
|
||||
val inheritedStaticSignatures =
|
||||
nonPublicSupertypes.flatMap { it.memberSignatures.filter { it.access.isStatic } }
|
||||
val inheritedStaticSignatures = nonPublicSupertypes.flatMap { it.memberSignatures.filter { it.access.isStatic }}
|
||||
|
||||
// not covered the case when there is public superclass after chain of private superclasses
|
||||
return this.copy(
|
||||
memberSignatures = memberSignatures + inheritedStaticSignatures,
|
||||
supertypes = supertypes - superName
|
||||
)
|
||||
return this.copy(memberSignatures = memberSignatures + inheritedStaticSignatures, supertypes = supertypes - superName)
|
||||
}
|
||||
|
||||
return filter { !it.isInNonPublicPackage() && it.isPublicAndAccessible() }
|
||||
.map { it.flattenNonPublicBases() }
|
||||
.filterNot { it.isNotUsedWhenEmpty && it.memberSignatures.isEmpty() }
|
||||
.filterNot { it.isNotUsedWhenEmpty && it.memberSignatures.isEmpty()}
|
||||
}
|
||||
|
||||
fun List<ClassBinarySignature>.dump() = dump(to = System.out)
|
||||
|
||||
fun <T : Appendable> List<ClassBinarySignature>.dump(to: T): T = to.apply {
|
||||
this@dump.forEach {
|
||||
fun <T : Appendable> List<ClassBinarySignature>.dump(to: T): T = to.apply { this@dump.forEach {
|
||||
append(it.signature).appendln(" {")
|
||||
it.memberSignatures.sortedWith(MEMBER_SORT_ORDER).forEach { append("\t").appendln(it.signature) }
|
||||
appendln("}\n")
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
/*
|
||||
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlinx.coroutines.tools
|
||||
package io.ktor.validator
|
||||
|
||||
import kotlinx.metadata.jvm.*
|
||||
import org.objectweb.asm.*
|
||||
import org.objectweb.asm.tree.*
|
||||
|
||||
@@ -29,32 +31,31 @@ data class ClassBinarySignature(
|
||||
val isEffectivelyPublic: Boolean,
|
||||
val isNotUsedWhenEmpty: Boolean
|
||||
) {
|
||||
|
||||
val signature: String
|
||||
get() = "${access.getModifierString()} class $name" + if (supertypes.isEmpty()) "" else " : ${supertypes.joinToString()}"
|
||||
|
||||
}
|
||||
|
||||
|
||||
interface MemberBinarySignature {
|
||||
val name: String
|
||||
val desc: String
|
||||
val jvmMember: JvmMemberSignature
|
||||
val name: String get() = jvmMember.name
|
||||
val desc: String get() = jvmMember.desc
|
||||
val access: AccessFlags
|
||||
val isPublishedApi: Boolean
|
||||
|
||||
fun isEffectivelyPublic(classAccess: AccessFlags, classVisibility: ClassVisibility?) =
|
||||
access.isPublic && !(access.isProtected && classAccess.isFinal)
|
||||
&& (findMemberVisibility(classVisibility)?.isPublic(isPublishedApi) ?: true)
|
||||
&& (findMemberVisibility(classVisibility)?.isPublic(isPublishedApi) ?: true)
|
||||
|
||||
fun findMemberVisibility(classVisibility: ClassVisibility?) =
|
||||
classVisibility?.members?.get(MemberSignature(name, desc))
|
||||
fun findMemberVisibility(classVisibility: ClassVisibility?): MemberVisibility? {
|
||||
return classVisibility?.findMember(jvmMember)
|
||||
}
|
||||
|
||||
val signature: String
|
||||
}
|
||||
|
||||
data class MethodBinarySignature(
|
||||
override val name: String,
|
||||
override val desc: String,
|
||||
override val jvmMember: JvmMethodSignature,
|
||||
override val isPublishedApi: Boolean,
|
||||
override val access: AccessFlags
|
||||
) : MemberBinarySignature {
|
||||
@@ -63,15 +64,41 @@ data class MethodBinarySignature(
|
||||
|
||||
override fun isEffectivelyPublic(classAccess: AccessFlags, classVisibility: ClassVisibility?) =
|
||||
super.isEffectivelyPublic(classAccess, classVisibility)
|
||||
&& !isAccessOrAnnotationsMethod()
|
||||
&& !isAccessOrAnnotationsMethod()
|
||||
&& !isDummyDefaultConstructor()
|
||||
|
||||
private fun isAccessOrAnnotationsMethod() =
|
||||
access.isSynthetic && (name.startsWith("access\$") || name.endsWith("\$annotations"))
|
||||
override fun findMemberVisibility(classVisibility: ClassVisibility?): MemberVisibility? {
|
||||
return super.findMemberVisibility(classVisibility) ?: classVisibility?.let { alternateDefaultSignature(it.name)?.let(it::findMember) }
|
||||
}
|
||||
|
||||
private fun isAccessOrAnnotationsMethod() = access.isSynthetic && (name.startsWith("access\$") || name.endsWith("\$annotations"))
|
||||
|
||||
private fun isDummyDefaultConstructor() = access.isSynthetic && name == "<init>" && desc == "(Lkotlin/jvm/internal/DefaultConstructorMarker;)V"
|
||||
|
||||
/**
|
||||
* Calculates the signature of this method without default parameters
|
||||
*
|
||||
* Returns `null` if this method isn't an entry point of a function
|
||||
* or a constructor with default parameters.
|
||||
* Returns an incorrect result, if there are more than 31 default parameters.
|
||||
*/
|
||||
private fun alternateDefaultSignature(className: String): JvmMethodSignature? {
|
||||
return when {
|
||||
!access.isSynthetic -> null
|
||||
name == "<init>" && "ILkotlin/jvm/internal/DefaultConstructorMarker;" in desc ->
|
||||
JvmMethodSignature(name, desc.replace("ILkotlin/jvm/internal/DefaultConstructorMarker;", ""))
|
||||
name.endsWith("\$default") && "ILjava/lang/Object;)" in desc ->
|
||||
JvmMethodSignature(
|
||||
name.removeSuffix("\$default"),
|
||||
desc.replace("ILjava/lang/Object;)", ")").replace("(L$className;", "(")
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class FieldBinarySignature(
|
||||
override val name: String,
|
||||
override val desc: String,
|
||||
override val jvmMember: JvmFieldSignature,
|
||||
override val isPublishedApi: Boolean,
|
||||
override val access: AccessFlags
|
||||
) : MemberBinarySignature {
|
||||
@@ -79,17 +106,12 @@ data class FieldBinarySignature(
|
||||
get() = "${access.getModifierString()} field $name $desc"
|
||||
|
||||
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
|
||||
return super.findMemberVisibility(classVisibility)
|
||||
?: takeIf { access.isStatic }?.let { super.findMemberVisibility(classVisibility?.companionVisibilities) }
|
||||
}
|
||||
}
|
||||
|
||||
val MemberBinarySignature.kind: Int
|
||||
private val MemberBinarySignature.kind: Int
|
||||
get() = when (this) {
|
||||
is FieldBinarySignature -> 1
|
||||
is MethodBinarySignature -> 2
|
||||
@@ -110,9 +132,7 @@ data class AccessFlags(val access: Int) {
|
||||
val isFinal: Boolean get() = isFinal(access)
|
||||
val isSynthetic: Boolean get() = isSynthetic(access)
|
||||
|
||||
fun getModifiers(): List<String> =
|
||||
ACCESS_NAMES.entries.mapNotNull { if (access and it.key != 0) it.value else null }
|
||||
|
||||
fun getModifiers(): List<String> = ACCESS_NAMES.entries.mapNotNull { if (access and it.key != 0) it.value else null }
|
||||
fun getModifierString(): String = getModifiers().joinToString(" ")
|
||||
}
|
||||
|
||||
@@ -125,13 +145,13 @@ fun isSynthetic(access: Int) = access and Opcodes.ACC_SYNTHETIC != 0
|
||||
|
||||
fun ClassNode.isEffectivelyPublic(classVisibility: ClassVisibility?) =
|
||||
isPublic(access)
|
||||
&& !isLocal()
|
||||
&& !isWhenMappings()
|
||||
&& (classVisibility?.isPublic(isPublishedApi()) ?: true)
|
||||
&& !isLocal()
|
||||
&& !isWhenMappings()
|
||||
&& (classVisibility?.isPublic(isPublishedApi()) ?: true)
|
||||
|
||||
|
||||
val ClassNode.innerClassNode: InnerClassNode? get() = innerClasses.singleOrNull { it.name == name }
|
||||
fun ClassNode.isLocal() = innerClassNode?.run { innerName == null && outerName == null } ?: false
|
||||
fun ClassNode.isLocal() = innerClassNode?.run { innerName == null && outerName == null} ?: false
|
||||
fun ClassNode.isInner() = innerClassNode != null
|
||||
fun ClassNode.isWhenMappings() = isSynthetic(access) && name.endsWith("\$WhenMappings")
|
||||
|
||||
@@ -145,51 +165,25 @@ fun MethodNode.isPublishedApi() = findAnnotation(publishedApiAnnotationName, inc
|
||||
fun FieldNode.isPublishedApi() = findAnnotation(publishedApiAnnotationName, includeInvisible = true) != null
|
||||
|
||||
|
||||
private object KotlinClassKind {
|
||||
const val FILE = 2
|
||||
const val SYNTHETIC_CLASS = 3
|
||||
const val MULTIPART_FACADE = 4
|
||||
|
||||
val FILE_OR_MULTIPART_FACADE_KINDS = listOf(FILE, MULTIPART_FACADE)
|
||||
}
|
||||
|
||||
fun ClassNode.isFileOrMultipartFacade() =
|
||||
kotlinClassKind.let { it != null && it in KotlinClassKind.FILE_OR_MULTIPART_FACADE_KINDS }
|
||||
|
||||
fun ClassNode.isDefaultImpls() =
|
||||
isInner() && name.endsWith("\$DefaultImpls") && kotlinClassKind == KotlinClassKind.SYNTHETIC_CLASS
|
||||
fun ClassNode.isDefaultImpls(metadata: KotlinClassMetadata?) = isInner() && name.endsWith("\$DefaultImpls") && metadata.isSyntheticClass()
|
||||
|
||||
|
||||
val ClassNode.kotlinClassKind: Int?
|
||||
get() = findAnnotation("kotlin/Metadata", false)?.get("k") as Int?
|
||||
|
||||
fun ClassNode.findAnnotation(annotationName: String, includeInvisible: Boolean = false) =
|
||||
findAnnotation(annotationName, visibleAnnotations, invisibleAnnotations, includeInvisible)
|
||||
|
||||
fun MethodNode.findAnnotation(annotationName: String, includeInvisible: Boolean = false) =
|
||||
findAnnotation(annotationName, visibleAnnotations, invisibleAnnotations, includeInvisible)
|
||||
|
||||
fun FieldNode.findAnnotation(annotationName: String, includeInvisible: Boolean = false) =
|
||||
findAnnotation(annotationName, visibleAnnotations, invisibleAnnotations, includeInvisible)
|
||||
fun ClassNode.findAnnotation(annotationName: String, includeInvisible: Boolean = false) = findAnnotation(annotationName, visibleAnnotations, invisibleAnnotations, includeInvisible)
|
||||
fun MethodNode.findAnnotation(annotationName: String, includeInvisible: Boolean = false) = findAnnotation(annotationName, visibleAnnotations, invisibleAnnotations, includeInvisible)
|
||||
fun FieldNode.findAnnotation(annotationName: String, includeInvisible: Boolean = false) = findAnnotation(annotationName, visibleAnnotations, invisibleAnnotations, includeInvisible)
|
||||
|
||||
operator fun AnnotationNode.get(key: String): Any? = values.annotationValue(key)
|
||||
|
||||
private fun List<Any>.annotationValue(key: String): Any? {
|
||||
for (index in (0..size / 2 - 1)) {
|
||||
for (index in (0 until size / 2)) {
|
||||
if (this[index * 2] == key)
|
||||
return this[index * 2 + 1]
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun findAnnotation(
|
||||
annotationName: String,
|
||||
visibleAnnotations: List<AnnotationNode>?,
|
||||
invisibleAnnotations: List<AnnotationNode>?,
|
||||
includeInvisible: Boolean
|
||||
): AnnotationNode? =
|
||||
private fun findAnnotation(annotationName: String, visibleAnnotations: List<AnnotationNode>?, invisibleAnnotations: List<AnnotationNode>?, includeInvisible: Boolean): AnnotationNode? =
|
||||
visibleAnnotations?.firstOrNull { it.refersToName(annotationName) }
|
||||
?: if (includeInvisible) invisibleAnnotations?.firstOrNull { it.refersToName(annotationName) } else null
|
||||
?: if (includeInvisible) invisibleAnnotations?.firstOrNull { it.refersToName(annotationName) } else null
|
||||
|
||||
fun AnnotationNode.refersToName(name: String) =
|
||||
desc.startsWith('L') && desc.endsWith(';') && desc.regionMatches(1, name, 0, name.length)
|
||||
fun AnnotationNode.refersToName(name: String) = desc.startsWith('L') && desc.endsWith(';') && desc.regionMatches(1, name, 0, name.length)
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package io.ktor.validator
|
||||
|
||||
import kotlinx.metadata.*
|
||||
import kotlinx.metadata.jvm.*
|
||||
import org.objectweb.asm.tree.*
|
||||
|
||||
val ClassNode.kotlinMetadata: KotlinClassMetadata?
|
||||
get() {
|
||||
val metadata = findAnnotation("kotlin/Metadata", false) ?: return null
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val header = with(metadata) {
|
||||
KotlinClassHeader(
|
||||
kind = get("k") as Int?,
|
||||
metadataVersion = (get("mv") as List<Int>?)?.toIntArray(),
|
||||
bytecodeVersion = (get("bv") as List<Int>?)?.toIntArray(),
|
||||
data1 = (get("d1") as List<String>?)?.toTypedArray(),
|
||||
data2 = (get("d2") as List<String>?)?.toTypedArray(),
|
||||
extraString = get("xs") as String?,
|
||||
packageName = get("pn") as String?,
|
||||
extraInt = get("xi") as Int?
|
||||
)
|
||||
}
|
||||
return KotlinClassMetadata.read(header)
|
||||
}
|
||||
|
||||
|
||||
fun KotlinClassMetadata?.isFileOrMultipartFacade() =
|
||||
this is KotlinClassMetadata.FileFacade || this is KotlinClassMetadata.MultiFileClassFacade
|
||||
|
||||
fun KotlinClassMetadata?.isSyntheticClass() = this is KotlinClassMetadata.SyntheticClass
|
||||
|
||||
|
||||
private val VISIBILITY_FLAGS_MAP = mapOf(
|
||||
Flag.IS_INTERNAL to "internal",
|
||||
Flag.IS_PRIVATE to "private",
|
||||
Flag.IS_PRIVATE_TO_THIS to "private",
|
||||
Flag.IS_PROTECTED to "protected",
|
||||
Flag.IS_PUBLIC to "public",
|
||||
Flag.IS_LOCAL to "local"
|
||||
)
|
||||
|
||||
private fun Flags.toVisibility() = VISIBILITY_FLAGS_MAP.entries.firstOrNull { (modifier) -> modifier(this) }?.value
|
||||
|
||||
private fun visitFunction(flags: Flags, name: String, addMember: (MemberVisibility) -> Unit) =
|
||||
object : KmFunctionVisitor() {
|
||||
var jvmDesc: JvmMemberSignature? = null
|
||||
override fun visitExtensions(type: KmExtensionType): KmFunctionExtensionVisitor? {
|
||||
if (type != JvmFunctionExtensionVisitor.TYPE) return null
|
||||
return object : JvmFunctionExtensionVisitor() {
|
||||
override fun visit(desc: JvmMethodSignature?) {
|
||||
jvmDesc = desc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitEnd() {
|
||||
jvmDesc?.let { jvmDesc ->
|
||||
addMember(MemberVisibility(jvmDesc, flags))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun visitConstructor(flags: Flags, addMember: (MemberVisibility) -> Unit) =
|
||||
object : KmConstructorVisitor() {
|
||||
var jvmDesc: JvmMemberSignature? = null
|
||||
override fun visitExtensions(type: KmExtensionType): KmConstructorExtensionVisitor? {
|
||||
if (type != JvmConstructorExtensionVisitor.TYPE) return null
|
||||
return object : JvmConstructorExtensionVisitor() {
|
||||
override fun visit(desc: JvmMethodSignature?) {
|
||||
jvmDesc = desc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitEnd() {
|
||||
jvmDesc?.let { signature ->
|
||||
addMember(MemberVisibility(signature, flags))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun visitProperty(flags: Flags, name: String, getterFlags: Flags, setterFlags: Flags, addMember: (MemberVisibility) -> Unit) =
|
||||
object : KmPropertyVisitor() {
|
||||
var _fieldDesc: JvmMemberSignature? = null
|
||||
var _getterDesc: JvmMemberSignature? = null
|
||||
var _setterDesc: JvmMemberSignature? = null
|
||||
|
||||
override fun visitExtensions(type: KmExtensionType): KmPropertyExtensionVisitor? {
|
||||
if (type != JvmPropertyExtensionVisitor.TYPE) return null
|
||||
return object : JvmPropertyExtensionVisitor() {
|
||||
override fun visit(fieldDesc: JvmFieldSignature?, getterDesc: JvmMethodSignature?, setterDesc: JvmMethodSignature?) {
|
||||
_fieldDesc = fieldDesc
|
||||
_getterDesc = getterDesc
|
||||
_setterDesc = setterDesc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitEnd() {
|
||||
_getterDesc?.let { addMember(MemberVisibility(it, getterFlags)) }
|
||||
_setterDesc?.let { addMember(MemberVisibility(it, setterFlags)) }
|
||||
_fieldDesc?.let {
|
||||
val fieldVisibility = when {
|
||||
Flag.Property.IS_LATEINIT(flags) -> setterFlags
|
||||
_getterDesc == null && _setterDesc == null -> flags // JvmField or const case
|
||||
else -> flagsOf(Flag.IS_PRIVATE)
|
||||
}
|
||||
addMember(MemberVisibility(it, fieldVisibility))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun visitPackage(addMember: (MemberVisibility) -> Unit) =
|
||||
object : KmPackageVisitor() {
|
||||
override fun visitFunction(flags: Flags, name: String): KmFunctionVisitor? {
|
||||
return visitFunction(flags, name, addMember)
|
||||
}
|
||||
|
||||
override fun visitProperty(flags: Flags, name: String, getterFlags: Flags, setterFlags: Flags): KmPropertyVisitor? {
|
||||
return visitProperty(flags, name, getterFlags, setterFlags, addMember)
|
||||
}
|
||||
|
||||
override fun visitTypeAlias(flags: Flags, name: String): KmTypeAliasVisitor? {
|
||||
return super.visitTypeAlias(flags, name)
|
||||
}
|
||||
}
|
||||
|
||||
private fun visitClass(flags: (Flags) -> Unit, addMember: (MemberVisibility) -> Unit) =
|
||||
object : KmClassVisitor() {
|
||||
override fun visit(flags: Flags, name: ClassName) {
|
||||
flags(flags)
|
||||
}
|
||||
|
||||
override fun visitFunction(flags: Flags, name: String): KmFunctionVisitor? {
|
||||
return visitFunction(flags, name, addMember)
|
||||
}
|
||||
|
||||
override fun visitProperty(flags: Flags, name: String, getterFlags: Flags, setterFlags: Flags): KmPropertyVisitor? {
|
||||
return visitProperty(flags, name, getterFlags, setterFlags, addMember)
|
||||
}
|
||||
|
||||
override fun visitConstructor(flags: Flags): KmConstructorVisitor? {
|
||||
return visitConstructor(flags, addMember)
|
||||
}
|
||||
|
||||
override fun visitTypeAlias(flags: Flags, name: String): KmTypeAliasVisitor? {
|
||||
return super.visitTypeAlias(flags, name)
|
||||
}
|
||||
}
|
||||
|
||||
fun KotlinClassMetadata.toClassVisibility(classNode: ClassNode): ClassVisibility? {
|
||||
var flags: Flags? = null
|
||||
var _facadeClassName: String? = null
|
||||
val members = mutableListOf<MemberVisibility>()
|
||||
val addMember: (MemberVisibility) -> Unit = { members.add(it) }
|
||||
|
||||
when (this) {
|
||||
is KotlinClassMetadata.Class ->
|
||||
this.accept(visitClass({ flags = it }, addMember))
|
||||
is KotlinClassMetadata.FileFacade ->
|
||||
this.accept(visitPackage(addMember))
|
||||
is KotlinClassMetadata.MultiFileClassPart -> {
|
||||
_facadeClassName = this.facadeClassName
|
||||
this.accept(visitPackage(addMember))
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
return ClassVisibility(classNode.name, flags, members.associateBy { it.member }, _facadeClassName)
|
||||
}
|
||||
|
||||
fun ClassNode.toClassVisibility() = kotlinMetadata?.toClassVisibility(this)
|
||||
|
||||
fun Sequence<ClassNode>.readKotlinVisibilities(): Map<String, ClassVisibility> =
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -1,65 +1,41 @@
|
||||
/*
|
||||
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlinx.coroutines.tools
|
||||
package io.ktor.validator
|
||||
|
||||
import com.google.gson.internal.*
|
||||
import com.google.gson.stream.*
|
||||
import java.io.*
|
||||
import kotlinx.metadata.*
|
||||
import kotlinx.metadata.jvm.*
|
||||
|
||||
data class ClassVisibility(
|
||||
class ClassVisibility(
|
||||
val name: String,
|
||||
val visibility: String?,
|
||||
val members: Map<MemberSignature, MemberVisibility>
|
||||
)
|
||||
val flags: Flags?,
|
||||
val members: Map<JvmMemberSignature, MemberVisibility>,
|
||||
val facadeClassName: String? = null
|
||||
) {
|
||||
val visibility get() = flags
|
||||
val isCompanion: Boolean get() = flags != null && Flag.Class.IS_COMPANION_OBJECT(flags)
|
||||
|
||||
data class MemberVisibility(val member: MemberSignature, val declaration: String?, val visibility: String?)
|
||||
data class MemberSignature(val name: String, val desc: String)
|
||||
var companionVisibilities: ClassVisibility? = null
|
||||
val partVisibilities = mutableListOf<ClassVisibility>()
|
||||
}
|
||||
|
||||
private fun isPublic(visibility: String?, isPublishedApi: Boolean) =
|
||||
visibility == null || visibility == "public" || visibility == "protected" || (isPublishedApi && visibility == "internal")
|
||||
fun ClassVisibility.findMember(signature: JvmMemberSignature): MemberVisibility? =
|
||||
members[signature] ?: partVisibilities.mapNotNull { it.members[signature] }.firstOrNull()
|
||||
|
||||
|
||||
data class MemberVisibility(val member: JvmMemberSignature, val visibility: Flags?)
|
||||
|
||||
private fun isPublic(visibility: Flags?, isPublishedApi: Boolean) =
|
||||
visibility == null
|
||||
|| Flag.IS_PUBLIC(visibility)
|
||||
|| Flag.IS_PROTECTED(visibility)
|
||||
|| (isPublishedApi && Flag.IS_INTERNAL(visibility))
|
||||
|
||||
fun ClassVisibility.isPublic(isPublishedApi: Boolean) = isPublic(visibility, isPublishedApi)
|
||||
fun MemberVisibility.isPublic(isPublishedApi: Boolean) = isPublic(visibility, isPublishedApi)
|
||||
|
||||
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> {
|
||||
check(declarationFile.exists()) { "Missing file $declarationFile"}
|
||||
val result = mutableListOf<ClassVisibility>()
|
||||
declarationFile.bufferedReader().use { reader ->
|
||||
val jsonReader = JsonReader(reader)
|
||||
jsonReader.beginArray()
|
||||
while (jsonReader.hasNext()) {
|
||||
val classObject = Streams.parse(jsonReader).asJsonObject
|
||||
result += with(classObject) {
|
||||
val name = getAsJsonPrimitive("class").asString
|
||||
val visibility = getAsJsonPrimitive("visibility")?.asString
|
||||
val members = getAsJsonArray("members").map { it ->
|
||||
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), declaration, visibility)
|
||||
}
|
||||
}
|
||||
ClassVisibility(name, visibility, members.associateByTo(hashMapOf()) { it.member })
|
||||
}
|
||||
}
|
||||
jsonReader.endArray()
|
||||
}
|
||||
|
||||
return result.associateByTo(hashMapOf()) { it.name }
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
|
||||
*/
|
||||
|
||||
package kotlinx.coroutines.tools
|
||||
package io.ktor.validator
|
||||
|
||||
import org.junit.*
|
||||
import org.junit.runner.*
|
||||
@@ -35,13 +35,12 @@ class PublicApiTest(
|
||||
fun testApi() {
|
||||
val libsDir = File(rootDir, "/build/libs").absoluteFile.normalize()
|
||||
val jarFile = getJarPath(libsDir)
|
||||
val kotlinJvmMappingsFiles = listOf(libsDir.resolve("../visibilities.json"))
|
||||
val visibilities =
|
||||
kotlinJvmMappingsFiles
|
||||
.map { readKotlinVisibilities(it) }
|
||||
.reduce { m1, m2 -> m1 + m2 }
|
||||
val api = getBinaryAPI(JarFile(jarFile), visibilities).filterOutNonPublic(nonPublicPackages)
|
||||
api.dumpAndCompareWith(File("reference-public-api").resolve("$moduleName.txt"))
|
||||
|
||||
println("Reading binary API from $jarFile")
|
||||
val api = getBinaryAPI(JarFile(jarFile)).filterOutNonPublic(nonPublicPackages)
|
||||
val target = File("reference-public-api").resolve("$moduleName.txt")
|
||||
|
||||
api.dumpAndCompareWith(target)
|
||||
}
|
||||
|
||||
private fun getJarPath(libsDir: File): File {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
|
||||
*/
|
||||
|
||||
package kotlinx.coroutines.tools
|
||||
package io.ktor.validator
|
||||
|
||||
import java.io.*
|
||||
import kotlin.test.*
|
||||
|
||||
@@ -5,7 +5,7 @@ public final class io/ktor/client/engine/android/Android : io/ktor/client/engine
|
||||
|
||||
public final class io/ktor/client/engine/android/AndroidClientEngine : io/ktor/client/engine/HttpClientJvmEngine {
|
||||
public fun <init> (Lio/ktor/client/engine/android/AndroidEngineConfig;)V
|
||||
public fun execute (Lio/ktor/client/call/HttpClientCall;Lio/ktor/client/request/HttpRequestData;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun execute (Lio/ktor/client/request/HttpRequestData;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public synthetic fun getConfig ()Lio/ktor/client/engine/HttpClientEngineConfig;
|
||||
public fun getConfig ()Lio/ktor/client/engine/android/AndroidEngineConfig;
|
||||
}
|
||||
@@ -14,10 +14,12 @@ public final class io/ktor/client/engine/android/AndroidEngineConfig : io/ktor/c
|
||||
public fun <init> ()V
|
||||
public final fun getConnectTimeout ()I
|
||||
public final fun getProxy ()Ljava/net/Proxy;
|
||||
public final fun getRequestConfig ()Lkotlin/jvm/functions/Function1;
|
||||
public final fun getSocketTimeout ()I
|
||||
public final fun getSslManager ()Lkotlin/jvm/functions/Function1;
|
||||
public final fun setConnectTimeout (I)V
|
||||
public final fun setProxy (Ljava/net/Proxy;)V
|
||||
public final fun setRequestConfig (Lkotlin/jvm/functions/Function1;)V
|
||||
public final fun setSocketTimeout (I)V
|
||||
public final fun setSslManager (Lkotlin/jvm/functions/Function1;)V
|
||||
}
|
||||
@@ -27,17 +29,3 @@ public final class io/ktor/client/engine/android/AndroidEngineContainer : io/kto
|
||||
public fun getFactory ()Lio/ktor/client/engine/HttpClientEngineFactory;
|
||||
}
|
||||
|
||||
public final class io/ktor/client/engine/android/AndroidHttpResponse : io/ktor/client/response/HttpResponse {
|
||||
public fun <init> (Lio/ktor/client/call/HttpClientCall;Lkotlinx/coroutines/io/ByteReadChannel;Lio/ktor/http/Headers;Lio/ktor/util/date/GMTDate;Lio/ktor/util/date/GMTDate;Lio/ktor/http/HttpStatusCode;Lio/ktor/http/HttpProtocolVersion;Lkotlin/coroutines/CoroutineContext;Ljava/net/HttpURLConnection;)V
|
||||
public fun close ()V
|
||||
public fun getCall ()Lio/ktor/client/call/HttpClientCall;
|
||||
public fun getContent ()Lkotlinx/coroutines/io/ByteReadChannel;
|
||||
public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
|
||||
public synthetic fun getExecutionContext ()Lkotlinx/coroutines/Job;
|
||||
public fun getHeaders ()Lio/ktor/http/Headers;
|
||||
public fun getRequestTime ()Lio/ktor/util/date/GMTDate;
|
||||
public fun getResponseTime ()Lio/ktor/util/date/GMTDate;
|
||||
public fun getStatus ()Lio/ktor/http/HttpStatusCode;
|
||||
public fun getVersion ()Lio/ktor/http/HttpProtocolVersion;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@ public final class io/ktor/client/features/auth/Auth$Feature : io/ktor/client/fe
|
||||
public synthetic fun prepare (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
|
||||
}
|
||||
|
||||
public final class io/ktor/client/features/auth/AuthKt {
|
||||
public static final fun Auth (Lio/ktor/client/HttpClientConfig;Lkotlin/jvm/functions/Function1;)V
|
||||
}
|
||||
|
||||
public abstract interface class io/ktor/client/features/auth/AuthProvider {
|
||||
public abstract fun addRequestHeaders (Lio/ktor/client/request/HttpRequestBuilder;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public abstract fun isApplicable (Lio/ktor/http/auth/HttpAuthHeader;)Z
|
||||
|
||||
@@ -22,22 +22,12 @@ public final class io/ktor/client/features/json/JsonFeature$Feature : io/ktor/cl
|
||||
public synthetic fun prepare (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
|
||||
}
|
||||
|
||||
public final class io/ktor/client/features/json/JsonFeatureKt {
|
||||
public static final fun Json (Lio/ktor/client/HttpClientConfig;Lkotlin/jvm/functions/Function1;)V
|
||||
}
|
||||
|
||||
public abstract interface class io/ktor/client/features/json/JsonSerializer {
|
||||
public abstract fun read (Lio/ktor/client/call/TypeInfo;Lkotlinx/io/core/Input;)Ljava/lang/Object;
|
||||
public abstract fun write (Ljava/lang/Object;)Lio/ktor/http/content/OutgoingContent;
|
||||
}
|
||||
|
||||
public final class io/ktor/client/features/json/serializer/KotlinxSerializer : io/ktor/client/features/json/JsonSerializer {
|
||||
public static final field Companion Lio/ktor/client/features/json/serializer/KotlinxSerializer$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Lkotlinx/serialization/json/Json;)V
|
||||
public synthetic fun <init> (Lkotlinx/serialization/json/Json;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun read (Lio/ktor/client/call/TypeInfo;Lkotlinx/io/core/Input;)Ljava/lang/Object;
|
||||
public final fun setListMapper (Lkotlin/reflect/KClass;Lkotlinx/serialization/KSerializer;)V
|
||||
public final fun setMapper (Lkotlin/reflect/KClass;Lkotlinx/serialization/KSerializer;)V
|
||||
public fun write (Ljava/lang/Object;)Lio/ktor/http/content/OutgoingContent;
|
||||
}
|
||||
|
||||
public final class io/ktor/client/features/json/serializer/KotlinxSerializer$Companion {
|
||||
}
|
||||
|
||||
|
||||
@@ -2,70 +2,41 @@ public final class io/ktor/client/engine/mock/MockEngine : io/ktor/client/engine
|
||||
public static final field Companion Lio/ktor/client/engine/mock/MockEngine$Companion;
|
||||
public fun <init> (Lio/ktor/client/engine/mock/MockEngineConfig;)V
|
||||
public fun close ()V
|
||||
public fun execute (Lio/ktor/client/call/HttpClientCall;Lio/ktor/client/request/HttpRequestData;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun execute (Lio/ktor/client/request/HttpRequestData;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public synthetic fun getConfig ()Lio/ktor/client/engine/HttpClientEngineConfig;
|
||||
public fun getConfig ()Lio/ktor/client/engine/mock/MockEngineConfig;
|
||||
public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
|
||||
public fun getDispatcher ()Lkotlinx/coroutines/CoroutineDispatcher;
|
||||
public final fun getRequestHistory ()Ljava/util/List;
|
||||
public final fun getResponseHistory ()Ljava/util/List;
|
||||
public fun install (Lio/ktor/client/HttpClient;)V
|
||||
}
|
||||
|
||||
public final class io/ktor/client/engine/mock/MockEngine$Companion : io/ktor/client/engine/HttpClientEngineFactory {
|
||||
public fun create (Lkotlin/jvm/functions/Function1;)Lio/ktor/client/engine/HttpClientEngine;
|
||||
public final fun invoke (Lkotlin/jvm/functions/Function3;)Lio/ktor/client/engine/mock/MockEngine;
|
||||
public final fun invoke (Lkotlin/jvm/functions/Function2;)Lio/ktor/client/engine/mock/MockEngine;
|
||||
}
|
||||
|
||||
public final class io/ktor/client/engine/mock/MockEngineConfig : io/ktor/client/engine/HttpClientEngineConfig {
|
||||
public fun <init> ()V
|
||||
public final fun addHandler (Lkotlin/jvm/functions/Function3;)V
|
||||
public final fun addHandler (Lkotlin/jvm/functions/Function2;)V
|
||||
public final fun getRequestHandlers ()Ljava/util/List;
|
||||
public final fun getReuseHandlers ()Z
|
||||
public final fun setReuseHandlers (Z)V
|
||||
}
|
||||
|
||||
public final class io/ktor/client/engine/mock/MockHttpRequest : io/ktor/client/request/HttpRequest {
|
||||
public fun <init> (Lio/ktor/client/call/HttpClientCall;Lio/ktor/http/HttpMethod;Lio/ktor/http/Url;Lio/ktor/util/Attributes;Lio/ktor/http/content/OutgoingContent;Lio/ktor/http/Headers;)V
|
||||
public fun getAttributes ()Lio/ktor/util/Attributes;
|
||||
public fun getCall ()Lio/ktor/client/call/HttpClientCall;
|
||||
public fun getContent ()Lio/ktor/http/content/OutgoingContent;
|
||||
public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
|
||||
public synthetic fun getExecutionContext ()Lkotlinx/coroutines/Job;
|
||||
public fun getHeaders ()Lio/ktor/http/Headers;
|
||||
public fun getMethod ()Lio/ktor/http/HttpMethod;
|
||||
public fun getUrl ()Lio/ktor/http/Url;
|
||||
}
|
||||
|
||||
public final class io/ktor/client/engine/mock/MockHttpRequestKt {
|
||||
public static final fun response (Lio/ktor/client/engine/mock/MockHttpRequest;Ljava/lang/String;Lio/ktor/http/HttpStatusCode;Lio/ktor/http/Headers;)Lio/ktor/client/engine/mock/MockHttpResponse;
|
||||
public static final fun response (Lio/ktor/client/engine/mock/MockHttpRequest;Lkotlinx/coroutines/io/ByteReadChannel;Lio/ktor/http/HttpStatusCode;Lio/ktor/http/Headers;)Lio/ktor/client/engine/mock/MockHttpResponse;
|
||||
public static final fun response (Lio/ktor/client/engine/mock/MockHttpRequest;[BLio/ktor/http/HttpStatusCode;Lio/ktor/http/Headers;)Lio/ktor/client/engine/mock/MockHttpResponse;
|
||||
public static synthetic fun response$default (Lio/ktor/client/engine/mock/MockHttpRequest;Ljava/lang/String;Lio/ktor/http/HttpStatusCode;Lio/ktor/http/Headers;ILjava/lang/Object;)Lio/ktor/client/engine/mock/MockHttpResponse;
|
||||
public static synthetic fun response$default (Lio/ktor/client/engine/mock/MockHttpRequest;Lkotlinx/coroutines/io/ByteReadChannel;Lio/ktor/http/HttpStatusCode;Lio/ktor/http/Headers;ILjava/lang/Object;)Lio/ktor/client/engine/mock/MockHttpResponse;
|
||||
public static synthetic fun response$default (Lio/ktor/client/engine/mock/MockHttpRequest;[BLio/ktor/http/HttpStatusCode;Lio/ktor/http/Headers;ILjava/lang/Object;)Lio/ktor/client/engine/mock/MockHttpResponse;
|
||||
public static final fun responseError (Lio/ktor/client/engine/mock/MockHttpRequest;Lio/ktor/http/HttpStatusCode;Ljava/lang/String;Lio/ktor/http/Headers;)Lio/ktor/client/engine/mock/MockHttpResponse;
|
||||
public static synthetic fun responseError$default (Lio/ktor/client/engine/mock/MockHttpRequest;Lio/ktor/http/HttpStatusCode;Ljava/lang/String;Lio/ktor/http/Headers;ILjava/lang/Object;)Lio/ktor/client/engine/mock/MockHttpResponse;
|
||||
public static final fun responseOk (Lio/ktor/client/engine/mock/MockHttpRequest;Ljava/lang/String;)Lio/ktor/client/engine/mock/MockHttpResponse;
|
||||
public static synthetic fun responseOk$default (Lio/ktor/client/engine/mock/MockHttpRequest;Ljava/lang/String;ILjava/lang/Object;)Lio/ktor/client/engine/mock/MockHttpResponse;
|
||||
public static final fun toRequest (Lio/ktor/client/request/HttpRequestData;Lio/ktor/client/call/HttpClientCall;)Lio/ktor/client/engine/mock/MockHttpRequest;
|
||||
}
|
||||
|
||||
public final class io/ktor/client/engine/mock/MockHttpResponse : io/ktor/client/response/HttpResponse {
|
||||
public fun <init> (Lio/ktor/client/call/HttpClientCall;Lio/ktor/http/HttpStatusCode;Lkotlinx/coroutines/io/ByteReadChannel;Lio/ktor/http/Headers;)V
|
||||
public synthetic fun <init> (Lio/ktor/client/call/HttpClientCall;Lio/ktor/http/HttpStatusCode;Lkotlinx/coroutines/io/ByteReadChannel;Lio/ktor/http/Headers;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun close ()V
|
||||
public fun getCall ()Lio/ktor/client/call/HttpClientCall;
|
||||
public fun getContent ()Lkotlinx/coroutines/io/ByteReadChannel;
|
||||
public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
|
||||
public synthetic fun getExecutionContext ()Lkotlinx/coroutines/Job;
|
||||
public fun getHeaders ()Lio/ktor/http/Headers;
|
||||
public fun getRequestTime ()Lio/ktor/util/date/GMTDate;
|
||||
public fun getResponseTime ()Lio/ktor/util/date/GMTDate;
|
||||
public fun getStatus ()Lio/ktor/http/HttpStatusCode;
|
||||
public fun getVersion ()Lio/ktor/http/HttpProtocolVersion;
|
||||
}
|
||||
|
||||
public final class io/ktor/client/engine/mock/MockUtilsKt {
|
||||
public static final fun respond (Ljava/lang/String;Lio/ktor/http/HttpStatusCode;Lio/ktor/http/Headers;)Lio/ktor/client/request/HttpResponseData;
|
||||
public static final fun respond (Lkotlinx/coroutines/io/ByteReadChannel;Lio/ktor/http/HttpStatusCode;Lio/ktor/http/Headers;)Lio/ktor/client/request/HttpResponseData;
|
||||
public static final fun respond ([BLio/ktor/http/HttpStatusCode;Lio/ktor/http/Headers;)Lio/ktor/client/request/HttpResponseData;
|
||||
public static synthetic fun respond$default (Ljava/lang/String;Lio/ktor/http/HttpStatusCode;Lio/ktor/http/Headers;ILjava/lang/Object;)Lio/ktor/client/request/HttpResponseData;
|
||||
public static synthetic fun respond$default (Lkotlinx/coroutines/io/ByteReadChannel;Lio/ktor/http/HttpStatusCode;Lio/ktor/http/Headers;ILjava/lang/Object;)Lio/ktor/client/request/HttpResponseData;
|
||||
public static synthetic fun respond$default ([BLio/ktor/http/HttpStatusCode;Lio/ktor/http/Headers;ILjava/lang/Object;)Lio/ktor/client/request/HttpResponseData;
|
||||
public static final fun respondBadRequest ()Lio/ktor/client/request/HttpResponseData;
|
||||
public static final fun respondError (Lio/ktor/http/HttpStatusCode;Ljava/lang/String;Lio/ktor/http/Headers;)Lio/ktor/client/request/HttpResponseData;
|
||||
public static synthetic fun respondError$default (Lio/ktor/http/HttpStatusCode;Ljava/lang/String;Lio/ktor/http/Headers;ILjava/lang/Object;)Lio/ktor/client/request/HttpResponseData;
|
||||
public static final fun respondOk (Ljava/lang/String;)Lio/ktor/client/request/HttpResponseData;
|
||||
public static synthetic fun respondOk$default (Ljava/lang/String;ILjava/lang/Object;)Lio/ktor/client/request/HttpResponseData;
|
||||
public static final fun toByteArray (Lio/ktor/http/content/OutgoingContent;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public static final fun toByteReadPacket (Lio/ktor/http/content/OutgoingContent;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
}
|
||||
|
||||
@@ -12,10 +12,9 @@ public final class io/ktor/client/engine/okhttp/OkHttpConfig : io/ktor/client/en
|
||||
public final fun setPreconfigured (Lokhttp3/OkHttpClient;)V
|
||||
}
|
||||
|
||||
public final class io/ktor/client/engine/okhttp/OkHttpEngine : io/ktor/client/engine/HttpClientJvmEngine, io/ktor/client/features/websocket/WebSocketEngine {
|
||||
public final class io/ktor/client/engine/okhttp/OkHttpEngine : io/ktor/client/engine/HttpClientJvmEngine {
|
||||
public fun <init> (Lio/ktor/client/engine/okhttp/OkHttpConfig;)V
|
||||
public fun execute (Lio/ktor/client/call/HttpClientCall;Lio/ktor/client/request/HttpRequestData;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun execute (Lio/ktor/client/request/HttpRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun execute (Lio/ktor/client/request/HttpRequestData;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public synthetic fun getConfig ()Lio/ktor/client/engine/HttpClientEngineConfig;
|
||||
public fun getConfig ()Lio/ktor/client/engine/okhttp/OkHttpConfig;
|
||||
}
|
||||
|
||||
@@ -282,6 +282,7 @@ public final class io/ktor/http/cio/websocket/DefaultWebSocketSessionKt {
|
||||
|
||||
public abstract class io/ktor/http/cio/websocket/Frame {
|
||||
public static final field Companion Lio/ktor/http/cio/websocket/Frame$Companion;
|
||||
public synthetic fun <init> (ZLio/ktor/http/cio/websocket/FrameType;[BLkotlinx/coroutines/DisposableHandle;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun copy ()Lio/ktor/http/cio/websocket/Frame;
|
||||
public final fun getBuffer ()Ljava/nio/ByteBuffer;
|
||||
public final fun getData ()[B
|
||||
|
||||
@@ -12,6 +12,7 @@ public final class io/ktor/http/BadContentTypeFormatException : java/lang/Except
|
||||
}
|
||||
|
||||
public abstract class io/ktor/http/CacheControl {
|
||||
public synthetic fun <init> (Lio/ktor/http/CacheControl$Visibility;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getVisibility ()Lio/ktor/http/CacheControl$Visibility;
|
||||
}
|
||||
|
||||
@@ -990,6 +991,7 @@ public final class io/ktor/http/auth/HeaderValueEncoding : java/lang/Enum {
|
||||
|
||||
public abstract class io/ktor/http/auth/HttpAuthHeader {
|
||||
public static final field Companion Lio/ktor/http/auth/HttpAuthHeader$Companion;
|
||||
public synthetic fun <init> (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getAuthScheme ()Ljava/lang/String;
|
||||
public abstract fun render ()Ljava/lang/String;
|
||||
public abstract fun render (Lio/ktor/http/auth/HeaderValueEncoding;)Ljava/lang/String;
|
||||
@@ -1196,6 +1198,7 @@ public abstract class io/ktor/http/content/OutgoingContent$WriteChannelContent :
|
||||
}
|
||||
|
||||
public abstract class io/ktor/http/content/PartData {
|
||||
public synthetic fun <init> (Lkotlin/jvm/functions/Function0;Lio/ktor/http/Headers;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getContentDisposition ()Lio/ktor/http/ContentDisposition;
|
||||
public final fun getContentType ()Lio/ktor/http/ContentType;
|
||||
public final fun getDispose ()Lkotlin/jvm/functions/Function0;
|
||||
|
||||
@@ -207,6 +207,7 @@ public final class io/ktor/network/sockets/SocketBuilder : io/ktor/network/socke
|
||||
|
||||
public abstract class io/ktor/network/sockets/SocketOptions {
|
||||
public static final field Companion Lio/ktor/network/sockets/SocketOptions$Companion;
|
||||
public synthetic fun <init> (Ljava/util/Map;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
protected fun copyCommon (Lio/ktor/network/sockets/SocketOptions;)V
|
||||
protected final fun getCustomOptions ()Ljava/util/Map;
|
||||
public final fun getReuseAddress ()Z
|
||||
@@ -218,6 +219,7 @@ public abstract class io/ktor/network/sockets/SocketOptions {
|
||||
}
|
||||
|
||||
public final class io/ktor/network/sockets/SocketOptions$AcceptorOptions : io/ktor/network/sockets/SocketOptions {
|
||||
public synthetic fun copy$ktor_network ()Lio/ktor/network/sockets/SocketOptions;
|
||||
}
|
||||
|
||||
public final class io/ktor/network/sockets/SocketOptions$Companion {
|
||||
@@ -225,6 +227,7 @@ public final class io/ktor/network/sockets/SocketOptions$Companion {
|
||||
}
|
||||
|
||||
public class io/ktor/network/sockets/SocketOptions$PeerSocketOptions : io/ktor/network/sockets/SocketOptions {
|
||||
public synthetic fun copy$ktor_network ()Lio/ktor/network/sockets/SocketOptions;
|
||||
protected fun copyCommon (Lio/ktor/network/sockets/SocketOptions;)V
|
||||
public final fun getReceiveBufferSize ()I
|
||||
public final fun getSendBufferSize ()I
|
||||
@@ -233,6 +236,8 @@ public class io/ktor/network/sockets/SocketOptions$PeerSocketOptions : io/ktor/n
|
||||
}
|
||||
|
||||
public final class io/ktor/network/sockets/SocketOptions$TCPClientSocketOptions : io/ktor/network/sockets/SocketOptions$PeerSocketOptions {
|
||||
public synthetic fun copy$ktor_network ()Lio/ktor/network/sockets/SocketOptions$PeerSocketOptions;
|
||||
public synthetic fun copy$ktor_network ()Lio/ktor/network/sockets/SocketOptions;
|
||||
public final fun getKeepAlive ()Ljava/lang/Boolean;
|
||||
public final fun getLingerSeconds ()I
|
||||
public final fun getNoDelay ()Z
|
||||
@@ -242,6 +247,8 @@ public final class io/ktor/network/sockets/SocketOptions$TCPClientSocketOptions
|
||||
}
|
||||
|
||||
public final class io/ktor/network/sockets/SocketOptions$UDPSocketOptions : io/ktor/network/sockets/SocketOptions$PeerSocketOptions {
|
||||
public synthetic fun copy$ktor_network ()Lio/ktor/network/sockets/SocketOptions$PeerSocketOptions;
|
||||
public synthetic fun copy$ktor_network ()Lio/ktor/network/sockets/SocketOptions;
|
||||
}
|
||||
|
||||
public final class io/ktor/network/sockets/SocketsKt {
|
||||
|
||||
Reference in New Issue
Block a user