K2 JVM: implement Java modules-related checkers
All existing tests use custom test data for FIR because the diagnostic text in FIR has to have a dot at the end. Also, the K2 checker doesn't check usages in imports because there are no "import checkers" in K2 right now, this will need to be fixed later if necessary. #KT-60797 Fixed
This commit is contained in:
committed by
Space Team
parent
ac901c6d07
commit
5ca7ab9801
+21
@@ -5390,6 +5390,27 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirJvmErrors.JAVA_MODULE_DOES_NOT_DEPEND_ON_MODULE) { firDiagnostic ->
|
||||
JavaModuleDoesNotDependOnModuleImpl(
|
||||
firDiagnostic.a,
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirJvmErrors.JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE) { firDiagnostic ->
|
||||
JavaModuleDoesNotReadUnnamedModuleImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirJvmErrors.JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE) { firDiagnostic ->
|
||||
JavaModuleDoesNotExportPackageImpl(
|
||||
firDiagnostic.a,
|
||||
firDiagnostic.b,
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirJvmErrors.JVM_DEFAULT_IN_DECLARATION) { firDiagnostic ->
|
||||
JvmDefaultInDeclarationImpl(
|
||||
firDiagnostic.a,
|
||||
|
||||
+15
@@ -3751,6 +3751,21 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = IllegalJavaLangRecordSupertype::class
|
||||
}
|
||||
|
||||
interface JavaModuleDoesNotDependOnModule : KtFirDiagnostic<PsiElement> {
|
||||
override val diagnosticClass get() = JavaModuleDoesNotDependOnModule::class
|
||||
val moduleName: String
|
||||
}
|
||||
|
||||
interface JavaModuleDoesNotReadUnnamedModule : KtFirDiagnostic<PsiElement> {
|
||||
override val diagnosticClass get() = JavaModuleDoesNotReadUnnamedModule::class
|
||||
}
|
||||
|
||||
interface JavaModuleDoesNotExportPackage : KtFirDiagnostic<PsiElement> {
|
||||
override val diagnosticClass get() = JavaModuleDoesNotExportPackage::class
|
||||
val moduleName: String
|
||||
val packageName: String
|
||||
}
|
||||
|
||||
interface JvmDefaultInDeclaration : KtFirDiagnostic<KtElement> {
|
||||
override val diagnosticClass get() = JvmDefaultInDeclaration::class
|
||||
val annotation: String
|
||||
|
||||
+18
@@ -4528,6 +4528,24 @@ internal class IllegalJavaLangRecordSupertypeImpl(
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.IllegalJavaLangRecordSupertype
|
||||
|
||||
internal class JavaModuleDoesNotDependOnModuleImpl(
|
||||
override val moduleName: String,
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.JavaModuleDoesNotDependOnModule
|
||||
|
||||
internal class JavaModuleDoesNotReadUnnamedModuleImpl(
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.JavaModuleDoesNotReadUnnamedModule
|
||||
|
||||
internal class JavaModuleDoesNotExportPackageImpl(
|
||||
override val moduleName: String,
|
||||
override val packageName: String,
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.JavaModuleDoesNotExportPackage
|
||||
|
||||
internal class JvmDefaultInDeclarationImpl(
|
||||
override val annotation: String,
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
|
||||
+13
-6
@@ -7,20 +7,16 @@ package org.jetbrains.kotlin.fir.checkers.generator.diagnostics
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature.*
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticList
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.PositioningStrategy
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.util.PrivateForInline
|
||||
|
||||
@Suppress("ClassName", "unused")
|
||||
@@ -135,6 +131,17 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") {
|
||||
val ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE by error<PsiElement>()
|
||||
}
|
||||
|
||||
val MODULES by object : DiagnosticGroup("JVM Modules") {
|
||||
val JAVA_MODULE_DOES_NOT_DEPEND_ON_MODULE by error<PsiElement> {
|
||||
parameter<String>("moduleName")
|
||||
}
|
||||
val JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE by error<PsiElement>()
|
||||
val JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE by error<PsiElement>() {
|
||||
parameter<String>("moduleName")
|
||||
parameter<String>("packageName")
|
||||
}
|
||||
}
|
||||
|
||||
val JVM_DEFAULT by object : DiagnosticGroup("JVM Default") {
|
||||
val JVM_DEFAULT_IN_DECLARATION by error<KtElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
|
||||
parameter<String>("annotation")
|
||||
|
||||
+5
@@ -99,6 +99,11 @@ object FirJvmErrors {
|
||||
val JVM_RECORD_EXTENDS_CLASS: KtDiagnosticFactory1<ConeKotlinType> by error1<PsiElement, ConeKotlinType>(SourceElementPositioningStrategies.ACTUAL_DECLARATION_NAME)
|
||||
val ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE: KtDiagnosticFactory0 by error0<PsiElement>()
|
||||
|
||||
// JVM Modules
|
||||
val JAVA_MODULE_DOES_NOT_DEPEND_ON_MODULE: KtDiagnosticFactory1<String> by error1<PsiElement, String>()
|
||||
val JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE: KtDiagnosticFactory0 by error0<PsiElement>()
|
||||
val JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE: KtDiagnosticFactory2<String, String> by error2<PsiElement, String, String>()
|
||||
|
||||
// JVM Default
|
||||
val JVM_DEFAULT_IN_DECLARATION: KtDiagnosticFactory1<String> by error1<KtElement, String>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||
val JVM_DEFAULT_WITH_COMPATIBILITY_IN_DECLARATION: KtDiagnosticFactory0 by error0<KtElement>()
|
||||
|
||||
+16
@@ -34,6 +34,9 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INAPPLICAB
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INAPPLICABLE_JVM_NAME
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INNER_JVM_RECORD
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JAVA_MODULE_DOES_NOT_DEPEND_ON_MODULE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JAVA_SAM_INTERFACE_CONSTRUCTOR_REFERENCE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JAVA_TYPE_MISMATCH
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_DEFAULT_IN_DECLARATION
|
||||
@@ -182,6 +185,19 @@ object FirJvmErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
map.put(NON_DATA_CLASS_JVM_RECORD, "Only data classes are allowed to be marked as '@JvmRecord'.")
|
||||
map.put(ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE, "Classes cannot have explicit 'java.lang.Record' supertype.")
|
||||
|
||||
map.put(
|
||||
JAVA_MODULE_DOES_NOT_DEPEND_ON_MODULE,
|
||||
"Symbol is declared in module ''{0}'', which the current module does not depend on.", STRING,
|
||||
)
|
||||
map.put(
|
||||
JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE,
|
||||
"Symbol is declared in an unnamed module which is not read by current module."
|
||||
)
|
||||
map.put(
|
||||
JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE,
|
||||
"Symbol is declared in module ''{0}'' which does not export package ''{1}''.", STRING, STRING,
|
||||
)
|
||||
|
||||
map.put(OVERRIDE_CANNOT_BE_STATIC, "Override member cannot be '@JvmStatic' in an object.")
|
||||
map.put(
|
||||
JVM_STATIC_NOT_IN_OBJECT_OR_CLASS_COMPANION,
|
||||
|
||||
+6
@@ -20,6 +20,7 @@ object JvmExpressionCheckers : ExpressionCheckers() {
|
||||
FirInterfaceDefaultMethodCallChecker,
|
||||
FirJavaSamInterfaceConstructorReferenceChecker,
|
||||
FirQualifiedAccessJavaNullabilityWarningChecker,
|
||||
FirJvmModuleAccessibilityQualifiedAccessChecker,
|
||||
)
|
||||
|
||||
override val propertyAccessExpressionCheckers: Set<FirPropertyAccessExpressionChecker>
|
||||
@@ -82,4 +83,9 @@ object JvmExpressionCheckers : ExpressionCheckers() {
|
||||
get() = setOf(
|
||||
FirJavaUnnecessaryNotNullChecker,
|
||||
)
|
||||
|
||||
override val resolvedQualifierCheckers: Set<FirResolvedQualifierChecker>
|
||||
get() = setOf(
|
||||
FirJvmModuleAccessibilityResolvedQualifierChecker,
|
||||
)
|
||||
}
|
||||
|
||||
+2
@@ -7,10 +7,12 @@ package org.jetbrains.kotlin.fir.analysis.jvm.checkers
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.type.*
|
||||
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.type.FirFunctionalTypeParameterNameChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.type.FirJvmModuleAccessibilityTypeChecker
|
||||
|
||||
object JvmTypeCheckers : TypeCheckers() {
|
||||
override val typeRefCheckers: Set<FirTypeRefChecker> = setOf(
|
||||
FirDynamicUnsupportedChecker,
|
||||
FirFunctionalTypeParameterNameChecker,
|
||||
FirJvmModuleAccessibilityTypeChecker,
|
||||
)
|
||||
}
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.jvm.checkers.expression
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.KtVirtualFileSourceFile
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirQualifiedAccessExpressionChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
|
||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.sourceElement
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.toReference
|
||||
import org.jetbrains.kotlin.fir.java.JavaBinarySourceElement
|
||||
import org.jetbrains.kotlin.fir.modules.javaModuleResolverProvider
|
||||
import org.jetbrains.kotlin.fir.packageFqName
|
||||
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||
import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
|
||||
|
||||
object FirJvmModuleAccessibilityQualifiedAccessChecker : FirQualifiedAccessExpressionChecker(MppCheckerKind.Common) {
|
||||
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val callableSymbol = expression.calleeReference.toResolvedCallableSymbol() ?: return
|
||||
if (callableSymbol.origin.fromSource) return
|
||||
|
||||
val containingClass = callableSymbol.containingClassLookupTag()
|
||||
if (containingClass != null) {
|
||||
val containingClassSymbol = containingClass.toFirRegularClassSymbol(context.session) ?: return
|
||||
checkClassAccess(context, containingClassSymbol, expression, reporter)
|
||||
} else {
|
||||
val containerSource = callableSymbol.containerSource as? JvmPackagePartSource ?: return
|
||||
val virtualFile = (containerSource.knownJvmBinaryClass as? VirtualFileKotlinClass)?.file ?: return
|
||||
checkPackageAccess(context, virtualFile, containerSource.className.packageFqName, expression, reporter)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun checkClassAccess(context: CheckerContext, symbol: FirClassSymbol<*>, element: FirElement, reporter: DiagnosticReporter) {
|
||||
if (symbol.origin.fromSource) return
|
||||
|
||||
@OptIn(SymbolInternals::class)
|
||||
val sourceElement = symbol.fir.sourceElement
|
||||
val virtualFile = when (sourceElement) {
|
||||
is JavaBinarySourceElement -> sourceElement.virtualFile
|
||||
is KotlinJvmBinarySourceElement -> (sourceElement.binaryClass as? VirtualFileKotlinClass)?.file ?: return
|
||||
else -> return
|
||||
}
|
||||
|
||||
checkPackageAccess(context, virtualFile, symbol.packageFqName(), element, reporter)
|
||||
}
|
||||
|
||||
internal fun checkPackageAccess(
|
||||
context: CheckerContext,
|
||||
fileFromPackage: VirtualFile,
|
||||
referencedPackageFqName: FqName,
|
||||
element: FirElement,
|
||||
reporter: DiagnosticReporter,
|
||||
) {
|
||||
val fileFromOurModule = (context.containingFile?.sourceFile as? KtVirtualFileSourceFile)?.virtualFile
|
||||
|
||||
val diagnostic = context.session.javaModuleResolverProvider.javaModuleResolver.checkAccessibility(
|
||||
fileFromOurModule, fileFromPackage, referencedPackageFqName
|
||||
) ?: return
|
||||
|
||||
val source = element.toReference(context.session)?.source ?: element.source
|
||||
when (diagnostic) {
|
||||
is JavaModuleResolver.AccessError.ModuleDoesNotExportPackage -> {
|
||||
reporter.reportOn(
|
||||
source, FirJvmErrors.JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE, diagnostic.dependencyModuleName,
|
||||
referencedPackageFqName.asString(), context,
|
||||
)
|
||||
}
|
||||
is JavaModuleResolver.AccessError.ModuleDoesNotReadModule -> {
|
||||
reporter.reportOn(source, FirJvmErrors.JAVA_MODULE_DOES_NOT_DEPEND_ON_MODULE, diagnostic.dependencyModuleName, context)
|
||||
}
|
||||
JavaModuleResolver.AccessError.ModuleDoesNotReadUnnamedModule -> {
|
||||
reporter.reportOn(source, FirJvmErrors.JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.jvm.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirResolvedQualifierChecker
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
|
||||
object FirJvmModuleAccessibilityResolvedQualifierChecker : FirResolvedQualifierChecker(MppCheckerKind.Common) {
|
||||
override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val symbol = expression.symbol
|
||||
if (symbol is FirClassSymbol<*>) {
|
||||
FirJvmModuleAccessibilityQualifiedAccessChecker.checkClassAccess(context, symbol, expression, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.jvm.checkers.type
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.type.FirTypeRefChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.expression.FirJvmModuleAccessibilityQualifiedAccessChecker
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeOrNull
|
||||
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
|
||||
|
||||
object FirJvmModuleAccessibilityTypeChecker : FirTypeRefChecker(MppCheckerKind.Common) {
|
||||
override fun check(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val classSymbol = typeRef.coneTypeOrNull?.toRegularClassSymbol(context.session) ?: return
|
||||
FirJvmModuleAccessibilityQualifiedAccessChecker.checkClassAccess(context, classSymbol, typeRef, reporter)
|
||||
}
|
||||
}
|
||||
+3
@@ -616,6 +616,9 @@ val FIR_NON_SUPPRESSIBLE_ERROR_NAMES: Set<String> = setOf(
|
||||
"DELEGATION_BY_IN_JVM_RECORD",
|
||||
"JVM_RECORD_EXTENDS_CLASS",
|
||||
"ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE",
|
||||
"JAVA_MODULE_DOES_NOT_DEPEND_ON_MODULE",
|
||||
"JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE",
|
||||
"JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE",
|
||||
"JVM_DEFAULT_IN_DECLARATION",
|
||||
"JVM_DEFAULT_WITH_COMPATIBILITY_IN_DECLARATION",
|
||||
"JVM_DEFAULT_WITH_COMPATIBILITY_NOT_ON_INTERFACE",
|
||||
|
||||
+3
-5
@@ -23,11 +23,7 @@ import org.jetbrains.kotlin.fir.analysis.jvm.checkers.FirJvmInlineCheckerCompone
|
||||
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.FirJvmPrimaryConstructorSuperTypeCheckerPlatformComponent
|
||||
import org.jetbrains.kotlin.fir.caches.FirCachesFactory
|
||||
import org.jetbrains.kotlin.fir.caches.FirThreadUnsafeCachesFactory
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOverloadabilityHelper
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeSpecificityComparatorProvider
|
||||
import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider
|
||||
import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProviderImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnnotationsPlatformSpecificSupportComponent
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationExtension
|
||||
import org.jetbrains.kotlin.fir.extensions.*
|
||||
import org.jetbrains.kotlin.fir.java.FirJavaVisibilityChecker
|
||||
@@ -39,6 +35,7 @@ import org.jetbrains.kotlin.fir.java.enhancement.FirAnnotationTypeQualifierResol
|
||||
import org.jetbrains.kotlin.fir.java.enhancement.FirEnhancedSymbolsStorage
|
||||
import org.jetbrains.kotlin.fir.java.enhancement.JavaCompilerRequiredAnnotationEnhancementProvider
|
||||
import org.jetbrains.kotlin.fir.java.scopes.JavaOverridabilityRules
|
||||
import org.jetbrains.kotlin.fir.modules.FirJavaModuleResolverProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirDeclarationOverloadabilityHelperImpl
|
||||
@@ -133,6 +130,7 @@ fun FirSession.registerJavaComponents(
|
||||
javaModuleResolver: JavaModuleResolver,
|
||||
predefinedComponents: FirSharableJavaComponents? = null,
|
||||
) {
|
||||
register(FirJavaModuleResolverProvider::class, FirJavaModuleResolverProvider(javaModuleResolver))
|
||||
val jsr305State = languageVersionSettings.getFlag(JvmAnalysisFlags.javaTypeEnhancementState)
|
||||
register(
|
||||
FirAnnotationTypeQualifierResolver::class,
|
||||
|
||||
@@ -5,10 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.java
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.SourceFile
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass
|
||||
|
||||
class JavaBinarySourceElement(val javaClass: BinaryJavaClass) : SourceElement {
|
||||
val virtualFile: VirtualFile
|
||||
get() = javaClass.virtualFile
|
||||
|
||||
override fun getContainingFile(): SourceFile = SourceFile.NO_SOURCE_FILE
|
||||
}
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.modules
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
|
||||
|
||||
class FirJavaModuleResolverProvider(val javaModuleResolver: JavaModuleResolver) : FirSessionComponent
|
||||
|
||||
val FirSession.javaModuleResolverProvider: FirJavaModuleResolverProvider by FirSession.sessionComponentAccessor()
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
compiler/testData/javaModules/automaticModuleInternalJdkPackageUsage/jvmStatUsage/Test.kt:1:8: error: symbol is declared in module 'jdk.internal.jvmstat' which does not export package 'sun.jvmstat.monitor'.
|
||||
val z: sun.jvmstat.monitor.Monitor? = null
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
COMPILATION_ERROR
|
||||
@@ -0,0 +1,13 @@
|
||||
compiler/testData/javaModules/noDependencyOnNamed/main/usage.kt:3:15: error: symbol is declared in module 'lib', which the current module does not depend on.
|
||||
fun test(foo: Foo) {
|
||||
^^^
|
||||
compiler/testData/javaModules/noDependencyOnNamed/main/usage.kt:4:9: error: symbol is declared in module 'lib', which the current module does not depend on.
|
||||
foo.field
|
||||
^^^^^
|
||||
compiler/testData/javaModules/noDependencyOnNamed/main/usage.kt:5:9: error: symbol is declared in module 'lib', which the current module does not depend on.
|
||||
foo.method()
|
||||
^^^^^^
|
||||
compiler/testData/javaModules/noDependencyOnNamed/main/usage.kt:6:5: error: symbol is declared in module 'lib', which the current module does not depend on.
|
||||
Foo()
|
||||
^^^
|
||||
COMPILATION_ERROR
|
||||
@@ -0,0 +1,13 @@
|
||||
compiler/testData/javaModules/noDependencyOnUnnamed/main/usage.kt:3:15: error: symbol is declared in an unnamed module which is not read by current module.
|
||||
fun test(foo: Foo) {
|
||||
^^^
|
||||
compiler/testData/javaModules/noDependencyOnUnnamed/main/usage.kt:4:9: error: symbol is declared in an unnamed module which is not read by current module.
|
||||
foo.field
|
||||
^^^^^
|
||||
compiler/testData/javaModules/noDependencyOnUnnamed/main/usage.kt:5:9: error: symbol is declared in an unnamed module which is not read by current module.
|
||||
foo.method()
|
||||
^^^^^^
|
||||
compiler/testData/javaModules/noDependencyOnUnnamed/main/usage.kt:6:5: error: symbol is declared in an unnamed module which is not read by current module.
|
||||
Foo()
|
||||
^^^
|
||||
COMPILATION_ERROR
|
||||
@@ -0,0 +1,37 @@
|
||||
compiler/testData/javaModules/simpleUseNonExportedPackage/moduleB/usage.kt:8:9: error: symbol is declared in module 'moduleA' which does not export package 'a.impl'.
|
||||
val a3: AImpl = A.getInstance()
|
||||
^^^^^
|
||||
compiler/testData/javaModules/simpleUseNonExportedPackage/moduleB/usage.kt:9:18: error: symbol is declared in module 'moduleA' which does not export package 'a.impl'.
|
||||
val a4: String = AImpl.method()
|
||||
^^^^^
|
||||
compiler/testData/javaModules/simpleUseNonExportedPackage/moduleB/usage.kt:9:24: error: symbol is declared in module 'moduleA' which does not export package 'a.impl'.
|
||||
val a4: String = AImpl.method()
|
||||
^^^^^^
|
||||
compiler/testData/javaModules/simpleUseNonExportedPackage/moduleB/usage.kt:10:18: error: symbol is declared in module 'moduleA' which does not export package 'a.impl'.
|
||||
val a5: String = AImpl.field
|
||||
^^^^^
|
||||
compiler/testData/javaModules/simpleUseNonExportedPackage/moduleB/usage.kt:10:24: error: symbol is declared in module 'moduleA' which does not export package 'a.impl'.
|
||||
val a5: String = AImpl.field
|
||||
^^^^^
|
||||
compiler/testData/javaModules/simpleUseNonExportedPackage/moduleB/usage.kt:14:9: error: symbol is declared in module 'moduleA' which does not export package 'a.impl'.
|
||||
val k3: KImpl = K.getInstance()
|
||||
^^^^^
|
||||
compiler/testData/javaModules/simpleUseNonExportedPackage/moduleB/usage.kt:15:18: error: symbol is declared in module 'moduleA' which does not export package 'a.impl'.
|
||||
val k4: String = KImpl.method()
|
||||
^^^^^
|
||||
compiler/testData/javaModules/simpleUseNonExportedPackage/moduleB/usage.kt:15:24: error: symbol is declared in module 'moduleA' which does not export package 'a.impl'.
|
||||
val k4: String = KImpl.method()
|
||||
^^^^^^
|
||||
compiler/testData/javaModules/simpleUseNonExportedPackage/moduleB/usage.kt:16:18: error: symbol is declared in module 'moduleA' which does not export package 'a.impl'.
|
||||
val k5: String = KImpl.field
|
||||
^^^^^
|
||||
compiler/testData/javaModules/simpleUseNonExportedPackage/moduleB/usage.kt:16:24: error: symbol is declared in module 'moduleA' which does not export package 'a.impl'.
|
||||
val k5: String = KImpl.field
|
||||
^^^^^
|
||||
compiler/testData/javaModules/simpleUseNonExportedPackage/moduleB/usage.kt:18:19: error: symbol is declared in module 'moduleA' which does not export package 'a.impl'.
|
||||
val kf1: String = fileField
|
||||
^^^^^^^^^
|
||||
compiler/testData/javaModules/simpleUseNonExportedPackage/moduleB/usage.kt:19:19: error: symbol is declared in module 'moduleA' which does not export package 'a.impl'.
|
||||
val kf2: String = fileMethod()
|
||||
^^^^^^^^^^
|
||||
COMPILATION_ERROR
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
compiler/testData/javaModules/specifyPathToModuleInfoInArguments/moduleB/usage.kt:9:5: error: symbol is declared in module 'moduleA' which does not export package 'unexported'.
|
||||
Unexported()
|
||||
^^^^^^^^^^
|
||||
compiler/testData/javaModules/specifyPathToModuleInfoInArguments/moduleB/usage.kt:13:5: error: unresolved reference 'Unrelated'.
|
||||
Unrelated()
|
||||
^^^^^^^^^
|
||||
COMPILATION_ERROR
|
||||
@@ -0,0 +1,4 @@
|
||||
compiler/testData/javaModules/unnamedDependsOnNamed/moduleB/usage.kt:7:5: error: symbol is declared in module 'moduleA' which does not export package 'foo.impl'.
|
||||
Impl() // should be error
|
||||
^^^^
|
||||
COMPILATION_ERROR
|
||||
+2
-11
@@ -9,14 +9,5 @@ import org.jetbrains.kotlin.config.LanguageVersion
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractFirJavaModulesIntegrationTest(jdkVersion: Int, jdkHome: File) : AbstractJavaModulesIntegrationTest(
|
||||
jdkVersion, jdkHome, maxOf(LanguageVersion.KOTLIN_2_0, LanguageVersion.LATEST_STABLE),
|
||||
) {
|
||||
override fun muteForK2(test: () -> Unit) {
|
||||
try {
|
||||
test()
|
||||
} catch (e: Throwable) {
|
||||
return
|
||||
}
|
||||
fail("Looks like this test can be unmuted. Remove the call to `muteForK2`.")
|
||||
}
|
||||
}
|
||||
jdkVersion, jdkHome, LanguageVersion.LATEST_STABLE,
|
||||
)
|
||||
|
||||
+6
-16
@@ -25,10 +25,6 @@ abstract class AbstractJavaModulesIntegrationTest(
|
||||
override val testDataPath: String
|
||||
get() = "compiler/testData/javaModules/"
|
||||
|
||||
protected open fun muteForK2(test: () -> Unit) {
|
||||
test()
|
||||
}
|
||||
|
||||
private fun module(
|
||||
name: String,
|
||||
modulePath: List<File> = emptyList(),
|
||||
@@ -120,8 +116,7 @@ abstract class AbstractJavaModulesIntegrationTest(
|
||||
module("moduleB", listOf(a))
|
||||
}
|
||||
|
||||
// TODO (KT-60797): missing JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE.
|
||||
fun testSimpleUseNonExportedPackage() = muteForK2 {
|
||||
fun testSimpleUseNonExportedPackage() {
|
||||
val a = module("moduleA")
|
||||
module("moduleB", listOf(a))
|
||||
}
|
||||
@@ -133,8 +128,7 @@ abstract class AbstractJavaModulesIntegrationTest(
|
||||
module("moduleD", listOf(a, b, c))
|
||||
}
|
||||
|
||||
// TODO (KT-60797): missing JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE.
|
||||
fun testUnnamedDependsOnNamed() = muteForK2 {
|
||||
fun testUnnamedDependsOnNamed() {
|
||||
val a = module("moduleA")
|
||||
module("moduleB", listOf(a), listOf("moduleA"))
|
||||
|
||||
@@ -174,8 +168,7 @@ abstract class AbstractJavaModulesIntegrationTest(
|
||||
}
|
||||
}
|
||||
|
||||
// TODO (KT-60797): missing JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE.
|
||||
fun testAutomaticModuleInternalJdkPackageUsage() = muteForK2 {
|
||||
fun testAutomaticModuleInternalJdkPackageUsage() {
|
||||
module("jvmStatUsage")
|
||||
}
|
||||
|
||||
@@ -217,8 +210,7 @@ abstract class AbstractJavaModulesIntegrationTest(
|
||||
module("moduleD", listOf(c, b, a))
|
||||
}
|
||||
|
||||
// TODO (KT-60797): missing JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE.
|
||||
fun testSpecifyPathToModuleInfoInArguments() = muteForK2 {
|
||||
fun testSpecifyPathToModuleInfoInArguments() {
|
||||
val a = module("moduleA")
|
||||
|
||||
val kotlinOptions = mutableListOf(
|
||||
@@ -349,15 +341,13 @@ abstract class AbstractJavaModulesIntegrationTest(
|
||||
})
|
||||
}
|
||||
|
||||
// TODO (KT-60797): missing JAVA_MODULE_DOES_NOT_DEPEND_ON_MODULE.
|
||||
fun testNoDependencyOnNamed() = muteForK2 {
|
||||
fun testNoDependencyOnNamed() {
|
||||
// This is a test on the JAVA_MODULE_DOES_NOT_DEPEND_ON_MODULE diagnostic.
|
||||
val lib = module("lib")
|
||||
module("main", listOf(lib), listOf("lib"))
|
||||
}
|
||||
|
||||
// TODO (KT-60797): missing JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE.
|
||||
fun testNoDependencyOnUnnamed() = muteForK2 {
|
||||
fun testNoDependencyOnUnnamed() {
|
||||
// This is a test on the JAVA_MODULE_DOES_NOT_READ_UNNAMED_MODULE diagnostic.
|
||||
// Most of the other tests in this class are compiling modules to jars, however here we need to compile the module to a directory.
|
||||
// The reason is twofold:
|
||||
|
||||
Reference in New Issue
Block a user