Report error on pre-release top level members
This commit is contained in:
+16
-6
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
|
|||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors.MISSING_DEPENDENCY_CLASS
|
import org.jetbrains.kotlin.diagnostics.Errors.MISSING_DEPENDENCY_CLASS
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors.PRE_RELEASE_CLASS
|
import org.jetbrains.kotlin.diagnostics.Errors.PRE_RELEASE_CLASS
|
||||||
@@ -32,14 +33,19 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
|||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.NotFoundClasses
|
import org.jetbrains.kotlin.serialization.deserialization.NotFoundClasses
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.utils.newLinkedHashSetWithExpectedSize
|
import org.jetbrains.kotlin.utils.newLinkedHashSetWithExpectedSize
|
||||||
|
|
||||||
object MissingDependencyClassChecker : CallChecker {
|
object MissingDependencyClassChecker : CallChecker {
|
||||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||||
for (diagnostic in collectDiagnostics(reportOn, resolvedCall.resultingDescriptor)) {
|
val resultingDescriptor = resolvedCall.resultingDescriptor
|
||||||
|
for (diagnostic in collectDiagnostics(reportOn, resultingDescriptor)) {
|
||||||
context.trace.report(diagnostic)
|
context.trace.report(diagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val containerSource = (resultingDescriptor as? DeserializedMemberDescriptor)?.containerSource
|
||||||
|
incompatibilityDiagnosticFor(containerSource, reportOn)?.let(context.trace::report)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun diagnosticFor(descriptor: ClassifierDescriptor, reportOn: PsiElement): Diagnostic? {
|
private fun diagnosticFor(descriptor: ClassifierDescriptor, reportOn: PsiElement): Diagnostic? {
|
||||||
@@ -47,10 +53,13 @@ object MissingDependencyClassChecker : CallChecker {
|
|||||||
return MISSING_DEPENDENCY_CLASS.on(reportOn, descriptor.fqNameSafe)
|
return MISSING_DEPENDENCY_CLASS.on(reportOn, descriptor.fqNameSafe)
|
||||||
}
|
}
|
||||||
|
|
||||||
val source = descriptor.source
|
return incompatibilityDiagnosticFor(descriptor.source, reportOn)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun incompatibilityDiagnosticFor(source: SourceElement?, reportOn: PsiElement): Diagnostic? {
|
||||||
if (source is DeserializedContainerSource && source.isPreReleaseInvisible) {
|
if (source is DeserializedContainerSource && source.isPreReleaseInvisible) {
|
||||||
// TODO: if at least one PRE_RELEASE_CLASS is reported, display a hint to disable the diagnostic
|
// TODO: if at least one PRE_RELEASE_CLASS is reported, display a hint to disable the diagnostic
|
||||||
return PRE_RELEASE_CLASS.on(reportOn, descriptor.fqNameSafe)
|
return PRE_RELEASE_CLASS.on(reportOn, source.presentableFqName)
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
@@ -88,9 +97,10 @@ object MissingDependencyClassChecker : CallChecker {
|
|||||||
element: PsiElement,
|
element: PsiElement,
|
||||||
languageVersionSettings: LanguageVersionSettings
|
languageVersionSettings: LanguageVersionSettings
|
||||||
) {
|
) {
|
||||||
diagnosticFor(targetDescriptor, element)?.let { diagnostic ->
|
diagnosticFor(targetDescriptor, element)?.let(trace::report)
|
||||||
trace.report(diagnostic)
|
|
||||||
}
|
val containerSource = (targetDescriptor as? DeserializedMemberDescriptor)?.containerSource
|
||||||
|
incompatibilityDiagnosticFor(containerSource, element)?.let(trace::report)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -3,3 +3,7 @@ package a
|
|||||||
open class A {
|
open class A {
|
||||||
class Nested
|
class Nested
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun foo() = ""
|
||||||
|
var bar = 42
|
||||||
|
typealias TA = String
|
||||||
|
|||||||
+22
-1
@@ -1,9 +1,18 @@
|
|||||||
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibrary/source.kt:5:16: error: class 'a.A' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
|
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibrary/source.kt:5:16: error: class 'a.A' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
|
||||||
fun baz(param: A) {
|
fun baz(param: A, nested: A.Nested) {
|
||||||
^
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibrary/source.kt:5:27: error: class 'a.A' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
|
||||||
|
fun baz(param: A, nested: A.Nested) {
|
||||||
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibrary/source.kt:5:29: error: class 'a.A.Nested' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
|
||||||
|
fun baz(param: A, nested: A.Nested) {
|
||||||
|
^
|
||||||
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibrary/source.kt:6:23: error: class 'a.A' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
|
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibrary/source.kt:6:23: error: class 'a.A' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
|
||||||
val constructor = A()
|
val constructor = A()
|
||||||
^
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibrary/source.kt:7:18: error: class 'a.A' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
|
||||||
|
val nested = A.Nested()
|
||||||
|
^
|
||||||
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibrary/source.kt:7:20: error: class 'a.A.Nested' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
|
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibrary/source.kt:7:20: error: class 'a.A.Nested' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
|
||||||
val nested = A.Nested()
|
val nested = A.Nested()
|
||||||
^
|
^
|
||||||
@@ -16,4 +25,16 @@ compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreRe
|
|||||||
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibrary/source.kt:9:30: error: class 'a.A' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
|
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibrary/source.kt:9:30: error: class 'a.A' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
|
||||||
val supertype = object : A() {}
|
val supertype = object : A() {}
|
||||||
^
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibrary/source.kt:11:13: error: class 'a.AKt' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
|
||||||
|
val x = foo()
|
||||||
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibrary/source.kt:12:13: error: class 'a.AKt' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
|
||||||
|
val y = bar
|
||||||
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibrary/source.kt:13:5: error: class 'a.AKt' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
|
||||||
|
bar = 239
|
||||||
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/releaseCompilerAgainstPreReleaseLibrary/source.kt:14:12: error: class 'a.AKt' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler
|
||||||
|
val z: TA = ""
|
||||||
|
^
|
||||||
COMPILATION_ERROR
|
COMPILATION_ERROR
|
||||||
+5
@@ -7,4 +7,9 @@ fun baz(param: A, nested: A.Nested) {
|
|||||||
val nested = A.Nested()
|
val nested = A.Nested()
|
||||||
val methodCall = param.method()
|
val methodCall = param.method()
|
||||||
val supertype = object : A() {}
|
val supertype = object : A() {}
|
||||||
|
|
||||||
|
val x = foo()
|
||||||
|
val y = bar
|
||||||
|
bar = 239
|
||||||
|
val z: TA = ""
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -60,7 +60,10 @@ class DeserializedDescriptorResolver(private val errorReporter: ErrorReporter) {
|
|||||||
val (nameResolver, packageProto) = parseProto(kotlinClass) {
|
val (nameResolver, packageProto) = parseProto(kotlinClass) {
|
||||||
JvmProtoBufUtil.readPackageDataFrom(data, strings)
|
JvmProtoBufUtil.readPackageDataFrom(data, strings)
|
||||||
}
|
}
|
||||||
val source = JvmPackagePartSource(kotlinClass)
|
val source = JvmPackagePartSource(
|
||||||
|
kotlinClass,
|
||||||
|
isPreReleaseInvisible = !IS_PRE_RELEASE && kotlinClass.classHeader.isPreRelease
|
||||||
|
)
|
||||||
return DeserializedPackageMemberScope(descriptor, packageProto, nameResolver, source, components) {
|
return DeserializedPackageMemberScope(descriptor, packageProto, nameResolver, source, components) {
|
||||||
// All classes are included into Java scope
|
// All classes are included into Java scope
|
||||||
emptyList()
|
emptyList()
|
||||||
|
|||||||
+11
-5
@@ -18,20 +18,26 @@ package org.jetbrains.kotlin.load.kotlin
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.SourceFile
|
import org.jetbrains.kotlin.descriptors.SourceFile
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||||
|
|
||||||
class JvmPackagePartSource(val className: JvmClassName, val facadeClassName: JvmClassName?) : DeserializedContainerSource {
|
class JvmPackagePartSource(
|
||||||
constructor(kotlinClass: KotlinJvmBinaryClass) : this(
|
val className: JvmClassName,
|
||||||
|
val facadeClassName: JvmClassName?,
|
||||||
|
override val isPreReleaseInvisible: Boolean = false
|
||||||
|
) : DeserializedContainerSource {
|
||||||
|
constructor(kotlinClass: KotlinJvmBinaryClass, isPreReleaseInvisible: Boolean = false) : this(
|
||||||
JvmClassName.byClassId(kotlinClass.classId),
|
JvmClassName.byClassId(kotlinClass.classId),
|
||||||
kotlinClass.classHeader.multifileClassName?.let {
|
kotlinClass.classHeader.multifileClassName?.let {
|
||||||
if (it.isNotEmpty()) JvmClassName.byInternalName(it) else null
|
if (it.isNotEmpty()) JvmClassName.byInternalName(it) else null
|
||||||
}
|
},
|
||||||
|
isPreReleaseInvisible
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO
|
override val presentableFqName: FqName
|
||||||
override val isPreReleaseInvisible: Boolean get() = false
|
get() = classId.asSingleFqName()
|
||||||
|
|
||||||
val simpleName: Name get() = Name.identifier(className.internalName.substringAfterLast('/'))
|
val simpleName: Name get() = Name.identifier(className.internalName.substringAfterLast('/'))
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -16,14 +16,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.load.kotlin
|
package org.jetbrains.kotlin.load.kotlin
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
|
||||||
import org.jetbrains.kotlin.descriptors.SourceFile
|
import org.jetbrains.kotlin.descriptors.SourceFile
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||||
|
|
||||||
class KotlinJvmBinarySourceElement(
|
class KotlinJvmBinarySourceElement(
|
||||||
val binaryClass: KotlinJvmBinaryClass,
|
val binaryClass: KotlinJvmBinaryClass,
|
||||||
override val isPreReleaseInvisible: Boolean = false
|
override val isPreReleaseInvisible: Boolean = false
|
||||||
) : DeserializedContainerSource {
|
) : DeserializedContainerSource {
|
||||||
|
override val presentableFqName: FqName
|
||||||
|
get() = binaryClass.classId.asSingleFqName()
|
||||||
|
|
||||||
override fun getContainingFile(): SourceFile = SourceFile.NO_SOURCE_FILE
|
override fun getContainingFile(): SourceFile = SourceFile.NO_SOURCE_FILE
|
||||||
|
|
||||||
override fun toString() = "${javaClass.simpleName}: $binaryClass"
|
override fun toString() = "${javaClass.simpleName}: $binaryClass"
|
||||||
|
|||||||
+4
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.serialization.deserialization.descriptors
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.*
|
import org.jetbrains.kotlin.descriptors.impl.*
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
import org.jetbrains.kotlin.protobuf.MessageLite
|
||||||
import org.jetbrains.kotlin.serialization.Flags
|
import org.jetbrains.kotlin.serialization.Flags
|
||||||
@@ -44,6 +45,9 @@ interface DeserializedMemberDescriptor : MemberDescriptor {
|
|||||||
interface DeserializedContainerSource : SourceElement {
|
interface DeserializedContainerSource : SourceElement {
|
||||||
// True iff this is container is "invisible" because it's loaded from a pre-release class and this compiler is a release
|
// True iff this is container is "invisible" because it's loaded from a pre-release class and this compiler is a release
|
||||||
val isPreReleaseInvisible: Boolean
|
val isPreReleaseInvisible: Boolean
|
||||||
|
|
||||||
|
// This FQ name should only be used for error messages
|
||||||
|
val presentableFqName: FqName
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DeserializedCallableMemberDescriptor : DeserializedMemberDescriptor, CallableMemberDescriptor
|
interface DeserializedCallableMemberDescriptor : DeserializedMemberDescriptor, CallableMemberDescriptor
|
||||||
|
|||||||
Reference in New Issue
Block a user