MultifileClassCodegen

- initial implementation
- new Kotlin file kinds + stub builder
This commit is contained in:
Dmitry Petrov
2015-09-04 23:33:54 +03:00
parent 9ab658b8d5
commit a00346a141
29 changed files with 798 additions and 78 deletions
@@ -22,30 +22,23 @@ import org.jetbrains.kotlin.psi.JetFile
public interface JvmFileClassInfo {
public val fileClassFqName: FqName
public val facadeClassFqName: FqName
public val kind: Kind
public enum class Kind {
FILE_CLASS,
MULTIFILE_CLASS_PART
;
}
public val isWithJvmName: Boolean
public val isMultifileClass: Boolean
}
public class JvmFileFacadeInfo(
override val fileClassFqName: FqName
public class JvmSimpleFileClassInfo(
override val fileClassFqName: FqName,
override val isWithJvmName: Boolean
) : JvmFileClassInfo {
override val facadeClassFqName: FqName
get() = fileClassFqName
override val kind: JvmFileClassInfo.Kind
get() = JvmFileClassInfo.Kind.FILE_CLASS
override val facadeClassFqName: FqName get() = fileClassFqName
override val isMultifileClass: Boolean get() = false
}
public class JvmMultifileFacadePartInfo(
public class JvmMultifileClassPartInfo(
override val fileClassFqName: FqName,
override val facadeClassFqName: FqName
) : JvmFileClassInfo {
override val kind: JvmFileClassInfo.Kind
get() = JvmFileClassInfo.Kind.MULTIFILE_CLASS_PART
override val isWithJvmName: Boolean get() = true
override val isMultifileClass: Boolean get() = true
}
@@ -30,7 +30,8 @@ public object JvmFileClassUtil {
public val JVM_NAME: FqName = FqName("kotlin.jvm.JvmName")
public val JVM_NAME_SHORT: String = JVM_NAME.shortName().asString()
// TODO @JvmMultifileClass
public val JVM_MULTIFILE_CLASS: FqName = FqName("kotlin.jvm.JvmMultifileClass")
public val JVM_MULTIFILE_CLASS_SHORT = JVM_MULTIFILE_CLASS.shortName().asString()
public @jvmStatic fun getFileClassInfo(file: JetFile, jvmFileClassAnnotations: ParsedJmvFileClassAnnotations?): JvmFileClassInfo =
if (jvmFileClassAnnotations != null)
@@ -40,13 +41,13 @@ public object JvmFileClassUtil {
public @jvmStatic fun getFileClassInfoForAnnotation(file: JetFile, jvmFileClassAnnotations: ParsedJmvFileClassAnnotations): JvmFileClassInfo =
if (jvmFileClassAnnotations.multipleFiles)
JvmMultifileFacadePartInfo(getHiddenPartFqName(file, jvmFileClassAnnotations),
getFacadeFqName(file, jvmFileClassAnnotations))
JvmMultifileClassPartInfo(getHiddenPartFqName(file, jvmFileClassAnnotations),
getFacadeFqName(file, jvmFileClassAnnotations))
else
JvmFileFacadeInfo(getFacadeFqName(file, jvmFileClassAnnotations))
JvmSimpleFileClassInfo(getFacadeFqName(file, jvmFileClassAnnotations), true)
public @jvmStatic fun getDefaultFileClassInfo(file: JetFile): JvmFileClassInfo =
JvmFileFacadeInfo(PackagePartClassUtils.getPackagePartFqName(file.packageFqName, file.name))
JvmSimpleFileClassInfo(PackagePartClassUtils.getPackagePartFqName(file.packageFqName, file.name), false)
public @jvmStatic fun getFacadeFqName(file: JetFile, jvmFileClassAnnotations: ParsedJmvFileClassAnnotations): FqName =
file.packageFqName.child(Name.identifier(jvmFileClassAnnotations.name))
@@ -59,31 +60,35 @@ public object JvmFileClassUtil {
public @jvmStatic fun parseJvmFileClass(annotations: Annotations): ParsedJmvFileClassAnnotations? {
val jvmName = annotations.findAnnotation(JVM_NAME)
// TODO @JvmMultifileClass
return if (jvmName != null) parseJvmFileClass(jvmName) else null
val jvmMultifileClass = annotations.findAnnotation(JVM_MULTIFILE_CLASS)
return jvmName?.let {
parseJvmFileClass(it, jvmMultifileClass)
}
}
public @jvmStatic fun parseJvmFileClass(jvmName: AnnotationDescriptor): ParsedJmvFileClassAnnotations {
public @jvmStatic fun parseJvmFileClass(jvmName: AnnotationDescriptor, jvmMultifileClass: AnnotationDescriptor?): ParsedJmvFileClassAnnotations {
val name = jvmName.allValueArguments.values().firstOrNull()?.let { (it as? StringValue)?.value }
return ParsedJmvFileClassAnnotations(name!!, false)
val isMultifileClassPart = jvmMultifileClass != null
return ParsedJmvFileClassAnnotations(name!!, isMultifileClassPart)
}
public @jvmStatic fun getFileClassInfoNoResolve(file: JetFile): JvmFileClassInfo =
getFileClassInfo(file, parseJvmNameOnFileNoResolve(file))
public @jvmStatic fun parseJvmNameOnFileNoResolve(file: JetFile): ParsedJmvFileClassAnnotations? =
findJvmNameOnFileNoResolve(file)?.let { parseJvmNameOnFileNoResolve(it) }
public @jvmStatic fun findJvmNameOnFileNoResolve(file: JetFile): JetAnnotationEntry? =
file.fileAnnotationList?.annotationEntries?.firstOrNull {
it.calleeExpression?.constructorReferenceExpression?.getReferencedName() == JVM_NAME_SHORT
findAnnotationEntryOnFileNoResolve(file, JVM_NAME_SHORT)?.let { annotationEntry ->
val nameExpr = annotationEntry.valueArguments.firstOrNull()?.getArgumentExpression() ?: return null
val name = getLiteralStringFromRestrictedConstExpression(nameExpr)
val isMultifileClassPart = findAnnotationEntryOnFileNoResolve(file, JVM_MULTIFILE_CLASS_SHORT) != null
name?.let {
ParsedJmvFileClassAnnotations(it, isMultifileClassPart)
}
}
public @jvmStatic fun parseJvmNameOnFileNoResolve(annotationEntry: JetAnnotationEntry): ParsedJmvFileClassAnnotations? {
val nameExpr = annotationEntry.valueArguments.firstOrNull()?.getArgumentExpression() ?: return null
val name = getLiteralStringFromRestrictedConstExpression(nameExpr)
return name?.let { ParsedJmvFileClassAnnotations(it, false) }
}
public @jvmStatic fun findAnnotationEntryOnFileNoResolve(file: JetFile, shortName: String): JetAnnotationEntry? =
file.fileAnnotationList?.annotationEntries?.firstOrNull {
it.calleeExpression?.constructorReferenceExpression?.getReferencedName() == shortName
}
private @jvmStatic fun getLiteralStringFromRestrictedConstExpression(argumentExpression: JetExpression?): String? {
val stringTemplate = argumentExpression as? JetStringTemplateExpression ?: return null
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.psi.JetClassOrObject
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.*
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
public enum class MemberKind { FIELD, METHOD }
@@ -39,13 +40,16 @@ public enum class JvmDeclarationOriginKind {
DELEGATION_TO_TRAIT_IMPL,
DELEGATION,
BRIDGE,
MULTIFILE_CLASS,
MULTIFILE_CLASS_PART,
SYNTHETIC // this means that there's no proper descriptor for this jvm declaration
}
public class JvmDeclarationOrigin(
public val originKind: JvmDeclarationOriginKind,
public val element: PsiElement?,
public val descriptor: DeclarationDescriptor?
public val descriptor: DeclarationDescriptor?,
public val multifileClassFqName: FqName? = null
) {
companion object {
public val NO_ORIGIN: JvmDeclarationOrigin = JvmDeclarationOrigin(OTHER, null, null)
@@ -67,6 +71,11 @@ public fun Bridge(descriptor: DeclarationDescriptor, element: PsiElement? = Desc
public fun PackageFacade(descriptor: PackageFragmentDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(PACKAGE_FACADE, null, descriptor)
public fun PackagePart(file: JetFile, descriptor: PackageFragmentDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(PACKAGE_PART, file, descriptor)
public fun MultifileClass(descriptor: PackageFragmentDescriptor, multifileClassFqName: FqName): JvmDeclarationOrigin =
JvmDeclarationOrigin(MULTIFILE_CLASS, null, descriptor, multifileClassFqName)
public fun MultifileClassPart(file: JetFile, descriptor: PackageFragmentDescriptor, multifileClassFqName: FqName): JvmDeclarationOrigin =
JvmDeclarationOrigin(MULTIFILE_CLASS_PART, file, descriptor, multifileClassFqName)
public fun TraitImpl(element: JetClassOrObject, descriptor: ClassDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(TRAIT_IMPL, element, descriptor)
public fun DelegationToTraitImpl(element: PsiElement?, descriptor: FunctionDescriptor): JvmDeclarationOrigin =
JvmDeclarationOrigin(DELEGATION_TO_TRAIT_IMPL, element, descriptor)