Move some declarations between 'descriptors' and 'deserialization'

- Move the following from 'deserialization' to 'descriptors':
  NotFoundClasses.kt
  AdditionalClassPartsProvider.kt
  ClassDescriptorFactory.kt
  PlatformDependentDeclarationFilter.kt
  findClassInModule.kt
- Move the following form 'descriptors' to 'deserialization':
  BuiltInSerializerProtocol.kt
  builtInsPackageFragmentProvider.kt
- Extract a marker interface from BuiltInsPackageFragment and move its
  implementation to 'deserialization'
- Change the type of parameters in PlatformDependentDeclarationFilter
  and AdditionalClassPartsProvider to ClassDescriptor

This will help in getting rid of the circular dependency of
'descriptors' <-> 'deserialization'
This commit is contained in:
Alexander Udalov
2017-06-02 12:45:09 +03:00
parent a4931568ba
commit cbaa676c3d
49 changed files with 166 additions and 146 deletions
@@ -0,0 +1,41 @@
/*
* 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.builtins
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
object BuiltInSerializerProtocol : SerializerExtensionProtocol(
ExtensionRegistryLite.newInstance().apply { BuiltInsProtoBuf.registerAllExtensions(this) },
BuiltInsProtoBuf.packageFqName,
BuiltInsProtoBuf.constructorAnnotation, BuiltInsProtoBuf.classAnnotation, BuiltInsProtoBuf.functionAnnotation,
BuiltInsProtoBuf.propertyAnnotation, BuiltInsProtoBuf.enumEntryAnnotation, BuiltInsProtoBuf.compileTimeValue,
BuiltInsProtoBuf.parameterAnnotation, BuiltInsProtoBuf.typeAnnotation, BuiltInsProtoBuf.typeParameterAnnotation
) {
val BUILTINS_FILE_EXTENSION = "kotlin_builtins"
fun getBuiltInsFilePath(fqName: FqName): String =
fqName.asString().replace('.', '/') + "/" + getBuiltInsFileName(fqName)
fun getBuiltInsFileName(fqName: FqName): String =
shortName(fqName) + "." + BUILTINS_FILE_EXTENSION
private fun shortName(fqName: FqName): String =
if (fqName.isRoot) "default-package" else fqName.shortName().asString()
}
@@ -0,0 +1,44 @@
/*
* 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.builtins
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.DeserializedPackageFragmentImpl
import org.jetbrains.kotlin.storage.StorageManager
import java.io.InputStream
class BuiltInsPackageFragmentImpl(
fqName: FqName,
storageManager: StorageManager,
module: ModuleDescriptor,
inputStream: InputStream
) : BuiltInsPackageFragment, DeserializedPackageFragmentImpl(fqName, storageManager, module, inputStream.use { stream ->
val version = BuiltInsBinaryVersion.readFrom(stream)
if (!version.isCompatible()) {
// TODO: report a proper diagnostic
throw UnsupportedOperationException(
"Kotlin built-in definition format version is not supported: " +
"expected ${BuiltInsBinaryVersion.INSTANCE}, actual $version. " +
"Please update Kotlin"
)
}
ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
}, containerSource = null)
@@ -0,0 +1,72 @@
/*
* 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.builtins
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.NotFoundClasses
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.descriptors.PackageFragmentProviderImpl
import org.jetbrains.kotlin.descriptors.deserialization.AdditionalClassPartsProvider
import org.jetbrains.kotlin.descriptors.deserialization.ClassDescriptorFactory
import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentDeclarationFilter
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.storage.StorageManager
import java.io.InputStream
fun createBuiltInPackageFragmentProvider(
storageManager: StorageManager,
module: ModuleDescriptor,
packageFqNames: Set<FqName>,
classDescriptorFactories: Iterable<ClassDescriptorFactory>,
platformDependentDeclarationFilter: PlatformDependentDeclarationFilter,
additionalClassPartsProvider: AdditionalClassPartsProvider = AdditionalClassPartsProvider.None,
loadResource: (String) -> InputStream?
): PackageFragmentProvider {
val packageFragments = packageFqNames.map { fqName ->
val resourcePath = BuiltInSerializerProtocol.getBuiltInsFilePath(fqName)
val inputStream = loadResource(resourcePath) ?: throw IllegalStateException("Resource not found in classpath: $resourcePath")
BuiltInsPackageFragmentImpl(fqName, storageManager, module, inputStream)
}
val provider = PackageFragmentProviderImpl(packageFragments)
val notFoundClasses = NotFoundClasses(storageManager, module)
val components = DeserializationComponents(
storageManager,
module,
DeserializationConfiguration.Default,
DeserializedClassDataFinder(provider),
AnnotationAndConstantLoaderImpl(module, notFoundClasses, BuiltInSerializerProtocol),
provider,
LocalClassifierTypeSettings.Default,
ErrorReporter.DO_NOTHING,
LookupTracker.DO_NOTHING,
FlexibleTypeDeserializer.ThrowException,
classDescriptorFactories,
notFoundClasses,
additionalClassPartsProvider = additionalClassPartsProvider,
platformDependentDeclarationFilter = platformDependentDeclarationFilter
)
for (packageFragment in packageFragments) {
packageFragment.components = components
}
return provider
}
@@ -1,38 +0,0 @@
/*
* Copyright 2010-2015 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.serialization.deserialization
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
import org.jetbrains.kotlin.types.KotlinType
interface AdditionalClassPartsProvider {
fun getSupertypes(classDescriptor: DeserializedClassDescriptor): Collection<KotlinType>
fun getFunctions(name: Name, classDescriptor: DeserializedClassDescriptor): Collection<SimpleFunctionDescriptor>
fun getConstructors(classDescriptor: DeserializedClassDescriptor): Collection<ClassConstructorDescriptor>
fun getFunctionsNames(classDescriptor: DeserializedClassDescriptor): Collection<Name>
object None : AdditionalClassPartsProvider {
override fun getSupertypes(classDescriptor: DeserializedClassDescriptor): Collection<KotlinType> = emptyList()
override fun getFunctions(name: Name, classDescriptor: DeserializedClassDescriptor): Collection<SimpleFunctionDescriptor> = emptyList()
override fun getFunctionsNames(classDescriptor: DeserializedClassDescriptor): Collection<Name> = emptyList()
override fun getConstructors(classDescriptor: DeserializedClassDescriptor): Collection<ClassConstructorDescriptor> = emptyList()
}
}
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.serialization.deserialization
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.NotFoundClasses
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
import org.jetbrains.kotlin.protobuf.MessageLite
@@ -1,31 +0,0 @@
/*
* Copyright 2010-2015 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.serialization.deserialization
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
interface ClassDescriptorFactory {
fun shouldCreateClass(packageFqName: FqName, name: Name): Boolean
fun createClass(classId: ClassId): ClassDescriptor?
// Note: do not rely on this function to return _all_ classes. Some factories can not enumerate all classes that they're able to create
fun getAllContributedClassesIfPossible(packageFqName: FqName): Collection<ClassDescriptor>
}
@@ -19,8 +19,11 @@ package org.jetbrains.kotlin.serialization.deserialization
import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol
import org.jetbrains.kotlin.builtins.BuiltInsBinaryVersion
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.NotFoundClasses
import org.jetbrains.kotlin.descriptors.PackagePartProvider
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.deserialization.AdditionalClassPartsProvider
import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentDeclarationFilter
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
@@ -1,104 +0,0 @@
/*
* Copyright 2010-2016 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.serialization.deserialization
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorBase
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.ClassTypeConstructorImpl
import org.jetbrains.kotlin.types.Variance
class NotFoundClasses(private val storageManager: StorageManager, private val module: ModuleDescriptor) {
/**
* @param typeParametersCount list of numbers of type parameters in this class and all its outer classes, starting from this class
*/
private data class ClassRequest(val classId: ClassId, val typeParametersCount: List<Int>)
private val packageFragments = storageManager.createMemoizedFunction<FqName, PackageFragmentDescriptor> { fqName ->
EmptyPackageFragmentDescriptor(module, fqName)
}
private val classes = storageManager.createMemoizedFunction<ClassRequest, ClassDescriptor> { (classId, typeParametersCount) ->
if (classId.isLocal) {
throw UnsupportedOperationException("Unresolved local class: $classId")
}
val container = classId.outerClassId?.let { outerClassId ->
getClass(outerClassId, typeParametersCount.drop(1))
} ?: packageFragments(classId.packageFqName)
// Treat a class with a nested ClassId as inner for simplicity, otherwise the outer type cannot have generic arguments
val isInner = classId.isNestedClass
MockClassDescriptor(storageManager, container, classId.shortClassName, isInner, typeParametersCount.firstOrNull() ?: 0)
}
class MockClassDescriptor internal constructor(
storageManager: StorageManager,
container: DeclarationDescriptor,
name: Name,
private val isInner: Boolean,
numberOfDeclaredTypeParameters: Int
) : ClassDescriptorBase(storageManager, container, name, SourceElement.NO_SOURCE, /* isExternal = */ false) {
private val typeParameters = (1..numberOfDeclaredTypeParameters).map { index ->
TypeParameterDescriptorImpl.createWithDefaultBound(
this, Annotations.EMPTY, false, Variance.INVARIANT, Name.identifier("T$index"), index
)
}
private val typeConstructor = ClassTypeConstructorImpl(this, /* isFinal = */ true, typeParameters, setOf(module.builtIns.anyType))
override fun getKind() = ClassKind.CLASS
override fun getModality() = Modality.FINAL
override fun getVisibility() = Visibilities.PUBLIC
override fun getTypeConstructor() = typeConstructor
override fun getDeclaredTypeParameters() = typeParameters
override fun isInner() = isInner
override fun isCompanionObject() = false
override fun isData() = false
override fun isHeader() = false
override fun isImpl() = false
override fun isExternal() = false
override val annotations: Annotations get() = Annotations.EMPTY
override fun getUnsubstitutedMemberScope() = MemberScope.Empty
override fun getStaticScope() = MemberScope.Empty
override fun getConstructors(): Collection<ClassConstructorDescriptor> = emptySet()
override fun getUnsubstitutedPrimaryConstructor(): ClassConstructorDescriptor? = null
override fun getCompanionObjectDescriptor(): ClassDescriptor? = null
override fun getSealedSubclasses(): Collection<ClassDescriptor> = emptyList()
override fun toString() = "class $name (not found)"
}
// We create different ClassDescriptor instances for types with the same ClassId but different number of type arguments.
// (This may happen when a class with the same FQ name is instantiated with different type arguments in different modules.)
// It's better than creating just one descriptor because otherwise would fail in multiple places where it's asserted that
// the number of type arguments in a type must be equal to the number of the type parameters of the class
fun getClass(classId: ClassId, typeParametersCount: List<Int>): ClassDescriptor {
return classes(ClassRequest(classId, typeParametersCount))
}
}
@@ -1,37 +0,0 @@
/*
* Copyright 2010-2016 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.serialization.deserialization
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
interface PlatformDependentDeclarationFilter {
fun isFunctionAvailable(classDescriptor: DeserializedClassDescriptor, functionDescriptor: SimpleFunctionDescriptor): Boolean
object All : PlatformDependentDeclarationFilter {
override fun isFunctionAvailable(classDescriptor: DeserializedClassDescriptor, functionDescriptor: SimpleFunctionDescriptor) = true
}
object NoPlatformDependent : PlatformDependentDeclarationFilter {
override fun isFunctionAvailable(classDescriptor: DeserializedClassDescriptor, functionDescriptor: SimpleFunctionDescriptor) =
!functionDescriptor.annotations.hasAnnotation(PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME)
}
}
val PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME = FqName("kotlin.internal.PlatformDependent")
@@ -18,9 +18,7 @@ package org.jetbrains.kotlin.serialization.deserialization
import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.builtins.transformRuntimeFunctionTypeToSuspendFunction
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.ClassId
@@ -19,6 +19,9 @@ package org.jetbrains.kotlin.serialization.deserialization
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
import org.jetbrains.kotlin.descriptors.deserialization.AdditionalClassPartsProvider
import org.jetbrains.kotlin.descriptors.deserialization.ClassDescriptorFactory
import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentDeclarationFilter
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.constants.ConstantValue
@@ -1,64 +0,0 @@
/*
* Copyright 2010-2015 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.serialization.deserialization
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.ClassId
fun ModuleDescriptor.findClassAcrossModuleDependencies(classId: ClassId): ClassDescriptor? {
val packageViewDescriptor = getPackage(classId.packageFqName)
val segments = classId.relativeClassName.pathSegments()
val topLevelClass = packageViewDescriptor.memberScope.getContributedClassifier(segments.first(), NoLookupLocation.FROM_DESERIALIZATION) as? ClassDescriptor ?: return null
var result = topLevelClass
for (name in segments.subList(1, segments.size)) {
result = result.unsubstitutedInnerClassesScope.getContributedClassifier(name, NoLookupLocation.FROM_DESERIALIZATION) as? ClassDescriptor ?: return null
}
return result
}
// Returns a mock class descriptor if no existing class is found.
// NB: the returned class has no type parameters and thus cannot be given arguments in types
fun ModuleDescriptor.findNonGenericClassAcrossDependencies(classId: ClassId, notFoundClasses: NotFoundClasses): ClassDescriptor {
val existingClass = findClassAcrossModuleDependencies(classId)
if (existingClass != null) return existingClass
// Take a list of N zeros, where N is the number of class names in the given ClassId
val typeParametersCount = generateSequence(classId, ClassId::getOuterClassId).map { 0 }.toList()
return notFoundClasses.getClass(classId, typeParametersCount)
}
fun ModuleDescriptor.findTypeAliasAcrossModuleDependencies(classId: ClassId): TypeAliasDescriptor? {
// TODO refactor with findClassAcrossModuleDependencies
// TODO what if typealias becomes a class / interface?
val packageViewDescriptor = getPackage(classId.packageFqName)
val segments = classId.relativeClassName.pathSegments()
val lastNameIndex = segments.size - 1
val topLevelClassifier = packageViewDescriptor.memberScope.getContributedClassifier(segments.first(), NoLookupLocation.FROM_DESERIALIZATION)
if (lastNameIndex == 0) return topLevelClassifier as? TypeAliasDescriptor
var currentClass = topLevelClassifier as? ClassDescriptor ?: return null
for (name in segments.subList(1, lastNameIndex)) {
currentClass = currentClass.unsubstitutedInnerClassesScope.getContributedClassifier(name, NoLookupLocation.FROM_DESERIALIZATION) as? ClassDescriptor ?: return null
}
val lastName = segments[lastNameIndex]
return currentClass.unsubstitutedMemberScope.getContributedClassifier(lastName, NoLookupLocation.FROM_DESERIALIZATION) as? TypeAliasDescriptor
}