K2: report JvmMultifileClass+JvmSynthetic error in JVM backend

Specifically, the case when not all parts of a multifile class are
annotated with `@JvmSynthetic`. Report the error on the
`@JvmMultifileClass` annotation instead of the package directive,
because the latter is difficult to find via IR. This fixes the test
FirLightTreeDiagnosticsTestWithJvmIrBackendGenerated.MultifileClasses.testJvmSynthetic.

 #KT-59586
This commit is contained in:
Alexander Udalov
2023-07-24 17:24:35 +02:00
parent 96ddd9bbf3
commit 6069aaee9c
3 changed files with 17 additions and 10 deletions
@@ -37,6 +37,8 @@ object JvmBackendErrors {
val INLINE_CALL_CYCLE by error1<PsiElement, Name>()
val NOT_ALL_MULTIFILE_CLASS_PARTS_ARE_JVM_SYNTHETIC by error0<PsiElement>()
init {
RootDiagnosticRendererFactory.registerFactory(KtDefaultJvmErrorMessages)
}
@@ -72,5 +74,9 @@ object KtDefaultJvmErrorMessages : BaseDiagnosticRendererFactory() {
map.put(JvmBackendErrors.SCRIPT_CAPTURING_ENUM_ENTRY, "Enum entry {0} captures the script class instance. Try to use class or anonymous object instead", STRING)
map.put(JvmBackendErrors.INLINE_CALL_CYCLE, "The ''{0}'' invocation is a part of inline cycle", NAME)
map.put(
JvmBackendErrors.NOT_ALL_MULTIFILE_CLASS_PARTS_ARE_JVM_SYNTHETIC,
"All of multi-file class parts should be annotated with @JvmSynthetic if at least one of them is"
)
}
}
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.MultifileFacadeFileEntry
import org.jetbrains.kotlin.backend.jvm.ir.fileParent
import org.jetbrains.kotlin.backend.jvm.ir.getKtFile
import org.jetbrains.kotlin.backend.jvm.isMultifileBridge
import org.jetbrains.kotlin.config.JvmAnalysisFlags
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
@@ -38,9 +37,10 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.JvmNames.JVM_SYNTHETIC_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.inline.INLINE_ONLY_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmBackendErrors
internal val generateMultifileFacadesPhase = makeCustomPhase<JvmBackendContext, IrModuleFragment>(
name = "GenerateMultifileFacades",
@@ -118,11 +118,12 @@ private fun generateMultifileFacades(
annotations = annotations + partClasses.first().getAnnotation(JVM_SYNTHETIC_ANNOTATION_FQ_NAME)!!.deepCopyWithSymbols()
} else if (nonJvmSyntheticParts.size < partClasses.size) {
for (part in nonJvmSyntheticParts) {
val partFile = part.fileParent.getKtFile() ?: error("Not a KtFile: ${part.render()} ${part.fileParent}")
val partFile = part.fileParent
// If at least one of parts is annotated with @JvmSynthetic, then all other parts should also be annotated.
// We report this error on the package directive for each non-@JvmSynthetic part.
context.state.diagnostics.report(
ErrorsJvm.NOT_ALL_MULTIFILE_CLASS_PARTS_ARE_JVM_SYNTHETIC.on(partFile.packageDirective ?: partFile)
// We report this error on the `@JvmMultifileClass` annotation of each non-@JvmSynthetic part.
val annotation = partFile.annotations.singleOrNull { it.isAnnotationWithEqualFqName(JvmNames.JVM_MULTIFILE_CLASS) }
context.ktDiagnosticReporter.at(annotation ?: partFile, partFile).report(
JvmBackendErrors.NOT_ALL_MULTIFILE_CLASS_PARTS_ARE_JVM_SYNTHETIC
)
}
}
@@ -3,8 +3,8 @@
// FILE: f.kt
@file:JvmName("Foo")
@file:JvmMultifileClass
<!NOT_ALL_MULTIFILE_CLASS_PARTS_ARE_JVM_SYNTHETIC!>package test<!>
<!NOT_ALL_MULTIFILE_CLASS_PARTS_ARE_JVM_SYNTHETIC!>@file:JvmMultifileClass<!>
package test
fun f() {}
@@ -20,8 +20,8 @@ val g = ""
// FILE: h.kt
@file:JvmName("Foo")
@file:JvmMultifileClass
<!NOT_ALL_MULTIFILE_CLASS_PARTS_ARE_JVM_SYNTHETIC!>package test<!>
<!NOT_ALL_MULTIFILE_CLASS_PARTS_ARE_JVM_SYNTHETIC!>@file:JvmMultifileClass<!>
package test
fun h() {}