From 70c91b2e7532dc7cb85d90ebba47e777341403ac Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Fri, 16 Oct 2015 21:52:11 +0300 Subject: [PATCH] Drop package facades: - getting rid of package facades in InlineCodegen & related stuff. Provide binary source element to top-level package members. --- .../kotlin/codegen/inline/InlineCodegen.java | 6 +-- .../codegen/inline/InlineCodegenUtil.java | 20 -------- .../codegen/inline/inlineCodegenUtils.kt | 21 ++++++-- .../kotlin/codegen/state/JetTypeMapper.java | 16 ++++-- .../kotlin/fileClasses/JvmFileClassUtil.kt | 18 ++----- .../load/kotlin/moduleVisibilityUtils.kt | 23 ++++++--- .../kotlin/load/java/descriptors/util.kt | 25 ++++++++++ .../descriptors/LazyJavaPackageFragment.kt | 5 +- .../KotlinJvmBinaryPackageSourceElement.kt | 49 +++++++++++++++++++ .../jps/incremental/IncrementalCacheImpl.kt | 15 ------ 10 files changed, 127 insertions(+), 71 deletions(-) create mode 100644 core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinaryPackageSourceElement.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java index 781e5befce6..fd74cc9976c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java @@ -769,9 +769,9 @@ public class InlineCodegen extends CallGenerator { if (incrementalCompilationComponents == null || targetId == null) return; IncrementalCache incrementalCache = incrementalCompilationComponents.getIncrementalCache(targetId); - String sourceFile = InlineCodegenUtilsKt.getClassFilePath(sourceDescriptor, incrementalCache); - String targetFile = InlineCodegenUtilsKt.getSourceFilePath(targetDescriptor); - incrementalCache.registerInline(sourceFile, jvmSignature.toString(), targetFile); + String classFilePath = InlineCodegenUtilsKt.getClassFilePath(sourceDescriptor, typeMapper, incrementalCache); + String sourceFilePath = InlineCodegenUtilsKt.getSourceFilePath(targetDescriptor); + incrementalCache.registerInline(classFilePath, jvmSignature.toString(), sourceFilePath); } @Override diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java index 67ca3978162..572290afe81 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java @@ -164,26 +164,6 @@ public class InlineCodegenUtil { return fileFinder.findVirtualFileWithHeader(new ClassId(packageFqName, Name.identifier(classNameWithDollars))); } - //TODO: navigate to inner classes - @Nullable - public static ClassId getContainerClassId(@NotNull DeclarationDescriptor referencedDescriptor) { - ClassOrPackageFragmentDescriptor - containerDescriptor = DescriptorUtils.getParentOfType(referencedDescriptor, ClassOrPackageFragmentDescriptor.class, false); - if (containerDescriptor instanceof PackageFragmentDescriptor) { - return PackageClassUtils.getPackageClassId(getFqName(containerDescriptor).toSafe()); - } - if (containerDescriptor instanceof ClassDescriptor) { - ClassId classId = DescriptorUtilsKt.getClassId((ClassDescriptor) containerDescriptor); - if (isInterface(containerDescriptor)) { - FqName relativeClassName = classId.getRelativeClassName(); - //TODO test nested trait fun inlining - classId = new ClassId(classId.getPackageFqName(), Name.identifier(relativeClassName.shortName().asString() + JvmAbi.DEFAULT_IMPLS_SUFFIX)); - } - return classId; - } - return null; - } - public static String getInlineName( @NotNull CodegenContext codegenContext, @NotNull JetTypeMapper typeMapper, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt index 400a0dc38db..0502d005c29 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt @@ -16,13 +16,15 @@ package org.jetbrains.kotlin.codegen.inline +import org.jetbrains.kotlin.codegen.state.JetTypeMapper import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryPackageSourceElement import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache -import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.source.PsiSourceElement +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor public val FunctionDescriptor.sourceFilePath: String @@ -32,19 +34,30 @@ public val FunctionDescriptor.sourceFilePath: String return containingFile?.virtualFile?.canonicalPath!! } -public fun FunctionDescriptor.getClassFilePath(cache: IncrementalCache): String { +public fun FunctionDescriptor.getClassFilePath(typeMapper: JetTypeMapper, cache: IncrementalCache): String { val container = containingDeclaration as? DeclarationDescriptorWithSource val source = container?.source return when (source) { + is KotlinJvmBinaryPackageSourceElement -> { + if (this !is DeserializedCallableMemberDescriptor) { + throw AssertionError("Expected DeserializedCallableMemberDescriptor, got: $this") + } + val kotlinClass = source.getContainingBinaryClass(this) ?: + throw AssertionError("Descriptor $this is not found, in: $source") + if (kotlinClass !is VirtualFileKotlinClass) { + throw AssertionError("Expected VirtualFileKotlinClass, got $kotlinClass") + } + kotlinClass.file.canonicalPath!! + } is KotlinJvmBinarySourceElement -> { assert(this is DeserializedSimpleFunctionDescriptor) { "Expected DeserializedSimpleFunctionDescriptor, got: $this" } val kotlinClass = source.binaryClass as VirtualFileKotlinClass kotlinClass.file.canonicalPath!! } else -> { - val classId = InlineCodegenUtil.getContainerClassId(this)!! - val className = JvmClassName.byClassId(classId).internalName + val implementationOwnerType = typeMapper.mapOwner(this) + val className = implementationOwnerType.internalName cache.getClassFilePath(className) } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java index 56b6798ee67..d67ab7a6adf 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java @@ -30,7 +30,6 @@ import org.jetbrains.kotlin.codegen.*; import org.jetbrains.kotlin.codegen.binding.CodegenBinding; import org.jetbrains.kotlin.codegen.binding.MutableClosure; import org.jetbrains.kotlin.codegen.binding.PsiCodegenPredictor; -import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil; import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.fileClasses.FileClasses; @@ -43,6 +42,7 @@ import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature. import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor; import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor; import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageScope; +import org.jetbrains.kotlin.load.kotlin.PackageClassUtils; import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider; import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache; import org.jetbrains.kotlin.name.*; @@ -241,8 +241,8 @@ public class JetTypeMapper { if (parentDeclaration instanceof PackageFragmentDescriptor) { containingClassesInfo = getPackageMemberContainingClassesInfo(deserializedDescriptor); } else { - containingClassesInfo = ContainingClassesInfo.forClassMemberOrNull( - InlineCodegenUtil.getContainerClassId(deserializedDescriptor)); + ClassId classId = getContainerClassIdForClassDescriptor((ClassDescriptor) parentDeclaration); + containingClassesInfo = ContainingClassesInfo.forClassMemberOrNull(classId); } if (containingClassesInfo == null) { throw new IllegalStateException("Couldn't find container for " + deserializedDescriptor.getName()); @@ -250,6 +250,16 @@ public class JetTypeMapper { return containingClassesInfo; } + private static ClassId getContainerClassIdForClassDescriptor(ClassDescriptor classDescriptor) { + ClassId classId = DescriptorUtilsKt.getClassId(classDescriptor); + if (isInterface(classDescriptor)) { + FqName relativeClassName = classId.getRelativeClassName(); + //TODO test nested trait fun inlining + classId = new ClassId(classId.getPackageFqName(), Name.identifier(relativeClassName.shortName().asString() + JvmAbi.DEFAULT_IMPLS_SUFFIX)); + } + return classId; + } + @Nullable private String getPackageMemberOwnerInternalName(@NotNull DeserializedCallableMemberDescriptor descriptor) { DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassUtil.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassUtil.kt index b50d53dc0ac..9a0f9df2294 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassUtil.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassUtil.kt @@ -20,6 +20,7 @@ import com.google.protobuf.MessageLite import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor +import org.jetbrains.kotlin.load.java.descriptors.getImplClassName import org.jetbrains.kotlin.load.kotlin.PackageClassUtils import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils import org.jetbrains.kotlin.name.FqName @@ -70,24 +71,11 @@ public object JvmFileClassUtil { @JvmStatic public fun getImplClassName(callable: DeserializedCallableMemberDescriptor): Name? = - getImplClassName(callable.proto, callable.nameResolver) + callable.getImplClassName() @JvmStatic public fun getImplClassName(proto: MessageLite, nameResolver: NameResolver): Name? = - when (proto) { - is ProtoBuf.Constructor -> - null - is ProtoBuf.Function -> - if (proto.hasExtension(JvmProtoBuf.methodImplClassName)) - proto.getExtension(JvmProtoBuf.methodImplClassName) - else null - is ProtoBuf.Property -> - if (proto.hasExtension(JvmProtoBuf.propertyImplClassName)) - proto.getExtension(JvmProtoBuf.propertyImplClassName) - else null - else -> - error("Unknown message: $proto") - }?.let { nameResolver.getName(it) } + getImplClassName(proto, nameResolver) @JvmStatic public fun getHiddenPartFqName(file: JetFile, jvmFileClassAnnotations: ParsedJmvFileClassAnnotations): FqName = diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/moduleVisibilityUtils.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/moduleVisibilityUtils.kt index feeb3f027ec..b87b87f250a 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/moduleVisibilityUtils.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/moduleVisibilityUtils.kt @@ -46,14 +46,21 @@ public fun isContainedByCompiledPartOfOurModule(descriptor: DeclarationDescripto if (outDirectory == null || packageFragment !is LazyJavaPackageFragment) return false val source = getSourceElement(descriptor) - if (source is KotlinJvmBinarySourceElement) { - val binaryClass = source.binaryClass - if (binaryClass is VirtualFileKotlinClass) { - val file = binaryClass.file - if (file.fileSystem.protocol == StandardFileSystems.FILE_PROTOCOL) { - val ioFile = VfsUtilCore.virtualToIoFile(file) - return ioFile.absolutePath.startsWith(outDirectory.absolutePath + File.separator); - } + + val binaryClass = when (source) { + is KotlinJvmBinarySourceElement -> + source.binaryClass + is KotlinJvmBinaryPackageSourceElement -> + source.getRepresentativeBinaryClass() + else -> + null + } + + if (binaryClass is VirtualFileKotlinClass) { + val file = binaryClass.file + if (file.fileSystem.protocol == StandardFileSystems.FILE_PROTOCOL) { + val ioFile = VfsUtilCore.virtualToIoFile(file) + return ioFile.absolutePath.startsWith(outDirectory.absolutePath + File.separator); } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/util.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/util.kt index 079af275654..520fdc0d449 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/util.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/util.kt @@ -16,13 +16,19 @@ package org.jetbrains.kotlin.load.java.descriptors +import com.google.protobuf.MessageLite import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaStaticClassScope +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.serialization.ProtoBuf +import org.jetbrains.kotlin.serialization.deserialization.NameResolver +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor +import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf import org.jetbrains.kotlin.types.JetType fun copyValueParameters( @@ -60,3 +66,22 @@ fun ClassDescriptor.getParentJavaStaticClassScope(): LazyJavaStaticClassScope? { return staticScope } + +fun DeserializedCallableMemberDescriptor.getImplClassName(): Name? = + getImplClassName(this.proto, this.nameResolver) + +fun getImplClassName(proto: MessageLite, nameResolver: NameResolver): Name? = + when (proto) { + is ProtoBuf.Constructor -> + null + is ProtoBuf.Function -> + if (proto.hasExtension(JvmProtoBuf.methodImplClassName)) + proto.getExtension(JvmProtoBuf.methodImplClassName) + else null + is ProtoBuf.Property -> + if (proto.hasExtension(JvmProtoBuf.propertyImplClassName)) + proto.getExtension(JvmProtoBuf.propertyImplClassName) + else null + else -> + error("Unknown message: $proto") + }?.let { nameResolver.getName(it) } \ No newline at end of file diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageFragment.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageFragment.kt index e3f20558d1c..e524071ac09 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageFragment.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageFragment.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.JavaPackage +import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryPackageSourceElement import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement import org.jetbrains.kotlin.load.kotlin.PackageClassUtils import org.jetbrains.kotlin.name.ClassId @@ -57,8 +58,6 @@ class LazyJavaPackageFragment( override fun toString() = "lazy java package fragment: $fqName" override fun getSource(): SourceElement { - // TODO source element for a bunch of Kotlin binary classes containing members of the same package - val representativeClass = kotlinBinaryClasses.firstOrNull() ?: return SourceElement.NO_SOURCE - return KotlinJvmBinarySourceElement(representativeClass) + return KotlinJvmBinaryPackageSourceElement(jPackage, kotlinBinaryClasses) } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinaryPackageSourceElement.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinaryPackageSourceElement.kt new file mode 100644 index 00000000000..814b7a7f05b --- /dev/null +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinaryPackageSourceElement.kt @@ -0,0 +1,49 @@ +/* + * 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.load.kotlin + +import org.jetbrains.kotlin.descriptors.SourceElement +import org.jetbrains.kotlin.descriptors.SourceFile +import org.jetbrains.kotlin.load.java.descriptors.getImplClassName +import org.jetbrains.kotlin.load.java.structure.JavaPackage +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor + + +class KotlinJvmBinaryPackageSourceElement( + private val jPackage: JavaPackage, + kotlinBinaryClasses: List +) : SourceElement { + private val implClassNameToBinaryClass = run { + val result = hashMapOf() + for (kotlinBinaryClass in kotlinBinaryClasses) { + result[kotlinBinaryClass.classId.shortClassName.asString()] = kotlinBinaryClass + } + result + } + + override fun toString(): String = "Binary package ${jPackage.getFqName()}: ${implClassNameToBinaryClass.keys}" + override fun getContainingFile(): SourceFile = SourceFile.NO_SOURCE_FILE + + public fun getRepresentativeBinaryClass(): KotlinJvmBinaryClass { + return implClassNameToBinaryClass.values.first() + } + + public fun getContainingBinaryClass(descriptor: DeserializedCallableMemberDescriptor): KotlinJvmBinaryClass? { + val name = descriptor.getImplClassName() ?: return null + return implClassNameToBinaryClass[name.asString()] + } +} \ No newline at end of file diff --git a/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt b/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt index 6c8b73f7535..1e462e4f7c9 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt @@ -520,21 +520,6 @@ public class IncrementalCacheImpl( value.dumpMap { java.lang.Long.toHexString(it) } } - private inner class PackagePartMap(storageFile: File) : BasicStringMap(storageFile, BooleanDataDescriptor.INSTANCE) { - public fun addPackagePart(className: JvmClassName) { - storage[className.internalName] = true - } - - public fun remove(className: JvmClassName) { - storage.remove(className.internalName) - } - - public fun isPackagePart(className: JvmClassName): Boolean = - className.internalName in storage - - override fun dumpValue(value: Boolean) = "" - } - private inner class MultifileClassFacadeMap(storageFile: File) : BasicStringMap>(storageFile, StringListExternalizer) { public fun add(facadeName: JvmClassName, partNames: List) { storage[facadeName.internalName] = partNames