Introduce JavaClassesSerializerExtension

It will be used to track java classes changes for incremental compilation

 #KT-17621 In Progress
This commit is contained in:
Denis Zharkov
2017-11-07 12:37:34 +03:00
parent c86dc0d7af
commit 1702775738
3 changed files with 127 additions and 26 deletions
@@ -0,0 +1,81 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental
import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.DescriptorSerializer
import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.java.JavaClassProtoBuf
// It uses BuiltInSerializerProtocol for annotations serialization
class JavaClassesSerializerExtension : KotlinSerializerExtensionBase(BuiltInSerializerProtocol) {
override fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder) {
super.serializeClass(descriptor, proto)
if (descriptor.visibility == JavaVisibilities.PACKAGE_VISIBILITY) {
proto.setExtension(JavaClassProtoBuf.isPackagePrivateClass, true)
}
}
override fun serializeConstructor(descriptor: ConstructorDescriptor, proto: ProtoBuf.Constructor.Builder) {
super.serializeConstructor(descriptor, proto)
if (descriptor.visibility == JavaVisibilities.PACKAGE_VISIBILITY) {
proto.setExtension(JavaClassProtoBuf.isPackagePrivateConstructor, true)
}
}
override fun serializeFunction(descriptor: FunctionDescriptor, proto: ProtoBuf.Function.Builder) {
super.serializeFunction(descriptor, proto)
if (descriptor.visibility == JavaVisibilities.PACKAGE_VISIBILITY) {
proto.setExtension(JavaClassProtoBuf.isPackagePrivateMethod, true)
}
if (descriptor.dispatchReceiverParameter == null) {
proto.setExtension(JavaClassProtoBuf.isStaticMethod, true)
}
}
override fun serializeProperty(descriptor: PropertyDescriptor, proto: ProtoBuf.Property.Builder) {
super.serializeProperty(descriptor, proto)
if (descriptor.visibility == JavaVisibilities.PACKAGE_VISIBILITY) {
proto.setExtension(JavaClassProtoBuf.isPackagePrivateField, true)
}
if (descriptor.dispatchReceiverParameter == null) {
proto.setExtension(JavaClassProtoBuf.isStaticField, true)
}
}
override fun shouldUseNormalizedVisibility() = true
override val customClassMembersProducer =
object : ClassMembersProducer {
override fun getCallableMembers(classDescriptor: ClassDescriptor) =
arrayListOf<CallableMemberDescriptor>().apply {
addAll(classDescriptor.unsubstitutedMemberScope.getSortedCallableDescriptors())
addAll(classDescriptor.staticScope.getSortedCallableDescriptors())
}
}
private fun MemberScope.getSortedCallableDescriptors(): Collection<CallableMemberDescriptor> =
DescriptorUtils.getAllDescriptors(this).filterIsInstance<CallableMemberDescriptor>()
.let { DescriptorSerializer.sort(it) }
}
@@ -71,7 +71,7 @@ class DescriptorSerializer private constructor(
val builder = ProtoBuf.Class.newBuilder()
val flags = Flags.getClassFlags(
hasAnnotations(classDescriptor), classDescriptor.visibility, classDescriptor.modality, classDescriptor.kind,
hasAnnotations(classDescriptor), normalizeVisibility(classDescriptor), classDescriptor.modality, classDescriptor.kind,
classDescriptor.isInner, classDescriptor.isCompanionObject, classDescriptor.isData, classDescriptor.isExternal,
classDescriptor.isExpect
)
@@ -101,18 +101,24 @@ class DescriptorSerializer private constructor(
builder.addConstructor(constructorProto(descriptor))
}
for (descriptor in sort(DescriptorUtils.getAllDescriptors(classDescriptor.defaultType.memberScope))) {
if (descriptor is CallableMemberDescriptor) {
if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) continue
val callableMembers =
extension.customClassMembersProducer?.getCallableMembers(classDescriptor)
?: sort(
DescriptorUtils.getAllDescriptors(classDescriptor.defaultType.memberScope)
.filterIsInstance<CallableMemberDescriptor>()
)
when (descriptor) {
is PropertyDescriptor -> builder.addProperty(propertyProto(descriptor))
is FunctionDescriptor -> builder.addFunction(functionProto(descriptor))
}
for (descriptor in callableMembers) {
if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) continue
when (descriptor) {
is PropertyDescriptor -> builder.addProperty(propertyProto(descriptor))
is FunctionDescriptor -> builder.addFunction(functionProto(descriptor))
}
}
for (descriptor in sort(DescriptorUtils.getAllDescriptors(classDescriptor.unsubstitutedInnerClassesScope))) {
val nestedClassifiers = sort(DescriptorUtils.getAllDescriptors(classDescriptor.unsubstitutedInnerClassesScope))
for (descriptor in nestedClassifiers) {
if (descriptor is TypeAliasDescriptor) {
builder.addTypeAlias(typeAliasProto(descriptor))
}
@@ -168,7 +174,7 @@ class DescriptorSerializer private constructor(
val hasAnnotations = descriptor.annotations.getAllAnnotations().isNotEmpty()
val propertyFlags = Flags.getAccessorFlags(hasAnnotations, descriptor.visibility, descriptor.modality, false, false, false)
val propertyFlags = Flags.getAccessorFlags(hasAnnotations, normalizeVisibility(descriptor), descriptor.modality, false, false, false)
val getter = descriptor.getter
if (getter != null) {
@@ -196,7 +202,7 @@ class DescriptorSerializer private constructor(
}
val flags = Flags.getPropertyFlags(
hasAnnotations, descriptor.visibility, descriptor.modality, descriptor.kind, descriptor.isVar,
hasAnnotations, normalizeVisibility(descriptor), descriptor.modality, descriptor.kind, descriptor.isVar,
hasGetter, hasSetter, hasConstant, descriptor.isConst, descriptor.isLateInit, descriptor.isExternal,
@Suppress("DEPRECATION") descriptor.isDelegated, descriptor.isExpect
)
@@ -240,13 +246,20 @@ class DescriptorSerializer private constructor(
return builder
}
private fun normalizeVisibility(descriptor: DeclarationDescriptorWithVisibility) =
// It can be necessary for Java classes serialization having package-private visibility
if (extension.shouldUseNormalizedVisibility())
descriptor.visibility.normalize()
else
descriptor.visibility
fun functionProto(descriptor: FunctionDescriptor): ProtoBuf.Function.Builder {
val builder = ProtoBuf.Function.newBuilder()
val local = createChildSerializer(descriptor)
val flags = Flags.getFunctionFlags(
hasAnnotations(descriptor), descriptor.visibility, descriptor.modality, descriptor.kind, descriptor.isOperator,
hasAnnotations(descriptor), normalizeVisibility(descriptor), descriptor.modality, descriptor.kind, descriptor.isOperator,
descriptor.isInfix, descriptor.isInline, descriptor.isTailrec, descriptor.isExternal, descriptor.isSuspend,
descriptor.isExpect
)
@@ -308,7 +321,7 @@ class DescriptorSerializer private constructor(
val local = createChildSerializer(descriptor)
val flags = Flags.getConstructorFlags(hasAnnotations(descriptor), descriptor.visibility, !descriptor.isPrimary)
val flags = Flags.getConstructorFlags(hasAnnotations(descriptor), normalizeVisibility(descriptor), !descriptor.isPrimary)
if (flags != builder.flags) {
builder.flags = flags
}
@@ -344,7 +357,7 @@ class DescriptorSerializer private constructor(
val builder = ProtoBuf.TypeAlias.newBuilder()
val local = createChildSerializer(descriptor)
val flags = Flags.getTypeAliasFlags(hasAnnotations(descriptor), descriptor.visibility)
val flags = Flags.getTypeAliasFlags(hasAnnotations(descriptor), normalizeVisibility(descriptor))
if (flags != builder.flags) {
builder.flags = flags
}
@@ -664,7 +677,16 @@ class DescriptorSerializer private constructor(
private fun getTypeParameterId(descriptor: TypeParameterDescriptor): Int =
typeParameters.intern(descriptor)
private fun getAccessorFlags(accessor: PropertyAccessorDescriptor): Int {
return Flags.getAccessorFlags(
hasAnnotations(accessor),
normalizeVisibility(accessor),
accessor.modality,
!accessor.isDefault,
accessor.isExternal,
accessor.isInline
)
}
companion object {
@JvmStatic
@@ -704,17 +726,6 @@ class DescriptorSerializer private constructor(
return serializer
}
private fun getAccessorFlags(accessor: PropertyAccessorDescriptor): Int {
return Flags.getAccessorFlags(
hasAnnotations(accessor),
accessor.visibility,
accessor.modality,
!accessor.isDefault,
accessor.isExternal,
accessor.isInline
)
}
private fun variance(variance: Variance): ProtoBuf.TypeParameter.Variance = when (variance) {
Variance.INVARIANT -> ProtoBuf.TypeParameter.Variance.INV
Variance.IN_VARIANCE -> ProtoBuf.TypeParameter.Variance.IN
@@ -27,6 +27,15 @@ abstract class SerializerExtension {
val annotationSerializer by lazy { AnnotationSerializer(stringTable) }
open fun shouldUseTypeTable(): Boolean = false
open fun shouldUseNormalizedVisibility(): Boolean = false
interface ClassMembersProducer {
fun getCallableMembers(classDescriptor: ClassDescriptor): Collection<CallableMemberDescriptor>
}
open val customClassMembersProducer: ClassMembersProducer?
get() = null
open fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder) {
}