FIR: load type qualifiers from module, package, and parent classes

This commit is contained in:
pyos
2021-08-19 17:54:40 +02:00
committed by teamcityserver
parent 24210aacc8
commit 090b90f62e
49 changed files with 121 additions and 673 deletions
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.load.java.JavaClassFinderImpl
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
import java.io.File
class PsiBasedProjectFileSearchScope(val psiSearchScope: GlobalSearchScope) : AbstractProjectFileSearchScope {
@@ -64,6 +65,9 @@ class PsiBasedProjectEnvironment(
): JavaSymbolProvider =
JavaSymbolProvider(firSession, baseModuleData, project, fileSearchScope.asPsiSearchScope())
override fun getJavaModuleResolver(): JavaModuleResolver =
JavaModuleResolver.getInstance(project)
override fun getPackagePartProvider(fileSearchScope: AbstractProjectFileSearchScope): PackagePartProvider =
getPackagePartProviderFn(fileSearchScope.asPsiSearchScope())
@@ -1,7 +1,7 @@
public open class A : R|kotlin/Any| {
@R|javax/annotation/Nullable|() public open field field: R|kotlin/String?|
public open fun foo(q: R|ft<kotlin/String, kotlin/String?>|, @R|javax/annotation/Nonnull|() x: R|@EnhancedNullability kotlin/String|, @R|javax/annotation/CheckForNull|() y: R|kotlin/CharSequence?|): R|ft<kotlin/String, kotlin/String?>|
public open fun foo(q: R|@EnhancedNullability kotlin/String|, @R|javax/annotation/Nonnull|() x: R|@EnhancedNullability kotlin/String|, @R|javax/annotation/CheckForNull|() y: R|kotlin/CharSequence?|): R|ft<kotlin/String, kotlin/String?>|
@R|javax/annotation/Nonnull|() public open fun bar(): R|@EnhancedNullability kotlin/String|
@@ -1,9 +1,9 @@
public open class A : R|kotlin/Any| {
public open field field: R|ft<kotlin/String, kotlin/String?>|
public open fun foo(x: R|ft<kotlin/String, kotlin/String?>|, @R|spr/Nullable|() y: R|kotlin/CharSequence?|): R|ft<kotlin/String, kotlin/String?>|
public open fun foo(x: R|@EnhancedNullability kotlin/String|, @R|spr/Nullable|() y: R|kotlin/CharSequence?|): R|@EnhancedNullability kotlin/String|
public open fun bar(): R|ft<kotlin/String, kotlin/String?>|
public open fun bar(): R|@EnhancedNullability kotlin/String|
@R|spr/Nullable|() public open fun baz(): R|ft<kotlin/collections/MutableList<ft<kotlin/String, kotlin/String?>>?, kotlin/collections/List<ft<kotlin/String, kotlin/String?>>?>|
@@ -21,8 +21,7 @@ import org.jetbrains.kotlin.fir.extensions.FirExtensionService
import org.jetbrains.kotlin.fir.extensions.FirPredicateBasedProvider
import org.jetbrains.kotlin.fir.extensions.FirRegisteredPluginAnnotations
import org.jetbrains.kotlin.fir.java.FirJavaVisibilityChecker
import org.jetbrains.kotlin.fir.java.enhancement.FirJavaTypeEnhancementStateComponent
import org.jetbrains.kotlin.fir.java.enhancement.FirJsr305StateContainer
import org.jetbrains.kotlin.fir.java.enhancement.FirAnnotationTypeQualifierResolver
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticNamesProvider
@@ -36,6 +35,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedClassIndex
import org.jetbrains.kotlin.fir.scopes.impl.FirDeclaredMemberScopeProvider
import org.jetbrains.kotlin.fir.types.FirCorrespondingSupertypesCache
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
// -------------------------- Required components --------------------------
@@ -62,9 +62,9 @@ fun FirSession.registerCliCompilerOnlyComponents() {
}
@OptIn(SessionConfiguration::class)
fun FirSession.registerCommonJavaComponents() {
fun FirSession.registerCommonJavaComponents(javaModuleResolver: JavaModuleResolver) {
val jsr305State = languageVersionSettings.getFlag(JvmAnalysisFlags.javaTypeEnhancementState)
register(FirJavaTypeEnhancementStateComponent::class, FirJavaTypeEnhancementStateComponent(jsr305State))
register(FirAnnotationTypeQualifierResolver::class, FirAnnotationTypeQualifierResolver(this, jsr305State, javaModuleResolver))
}
// -------------------------- Resolve components --------------------------
@@ -100,7 +100,6 @@ fun FirSession.registerJavaSpecificResolveComponents() {
register(ConeCallConflictResolverFactory::class, JvmCallConflictResolverFactory)
register(FirPlatformClassMapper::class, FirJavaClassMapper(this))
register(FirSyntheticNamesProvider::class, FirJavaSyntheticNamesProvider)
register(FirJsr305StateContainer::class, FirJsr305StateContainer.Default)
register(FirOverridesBackwardCompatibilityHelper::class, FirJvmOverridesBackwardCompatibilityHelper)
}
@@ -136,7 +136,7 @@ object FirSessionFactory {
registerModuleData(moduleData)
registerCliCompilerOnlyComponents()
registerCommonComponents(languageVersionSettings)
registerCommonJavaComponents()
registerCommonJavaComponents(projectEnvironment.getJavaModuleResolver())
registerResolveComponents(lookupTracker)
registerJavaSpecificResolveComponents()
@@ -208,7 +208,7 @@ object FirSessionFactory {
registerCliCompilerOnlyComponents()
registerCommonComponents(languageVersionSettings)
registerCommonJavaComponents()
registerCommonJavaComponents(projectEnvironment.getJavaModuleResolver())
val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
import org.jetbrains.kotlin.load.java.JavaClassFinder
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
import java.io.File
interface AbstractProjectFileSearchScope {
@@ -50,6 +51,8 @@ interface AbstractProjectEnvironment {
fileSearchScope: AbstractProjectFileSearchScope
): JavaSymbolProvider
fun getJavaModuleResolver(): JavaModuleResolver
fun getPackagePartProvider(fileSearchScope: AbstractProjectFileSearchScope): PackagePartProvider
fun registerAsJavaElementFinder(firSession: FirSession)
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.load.java.JavaClassFinder
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.load.java.structure.impl.JavaElementImpl
import org.jetbrains.kotlin.load.java.structure.impl.JavaPackageImpl
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
@@ -214,6 +215,7 @@ class JavaSymbolProvider(
modality = if (classKind == ClassKind.ANNOTATION_CLASS || classKind == ClassKind.ENUM_CLASS) Modality.FINAL else javaClass.modality
this.isTopLevel = outerClassId == null
isStatic = javaClass.isStatic
javaPackage = packageCache.getValue(classSymbol.classId.packageFqName)
this.javaTypeParameterStack = javaTypeParameterStack
existingNestedClassifierNames += javaClass.innerClassNames
scopeProvider = this@JavaSymbolProvider.scopeProvider
@@ -390,7 +392,7 @@ class JavaSymbolProvider(
returnTypeRef = returnType.toFirJavaTypeRef(this@JavaSymbolProvider.session, javaTypeParameterStack)
isVar = !javaField.isFinal
isStatic = javaField.isStatic
annotationBuilder = { javaField.annotations.map { it.toFirAnnotationCall(session, javaTypeParameterStack) } }
annotationBuilder = { javaField.convertAnnotationsToFir(session, javaTypeParameterStack) }
initializer = convertJavaInitializerToFir(javaField.initializerValue)
if (!javaField.isStatic) {
@@ -432,7 +434,7 @@ class JavaSymbolProvider(
this@JavaSymbolProvider.session, moduleData, index, javaTypeParameterStack,
)
}
annotationBuilder = { javaMethod.annotations.map { it.toFirAnnotationCall(session, javaTypeParameterStack) } }
annotationBuilder = { javaMethod.convertAnnotationsToFir(session, javaTypeParameterStack) }
status = FirResolvedDeclarationStatusImpl(
javaMethod.visibility,
javaMethod.modality,
@@ -508,7 +510,7 @@ class JavaSymbolProvider(
if (javaConstructor != null) {
this.typeParameters += javaConstructor.typeParameters.convertTypeParameters(javaTypeParameterStack)
annotationBuilder = { javaConstructor.annotations.map { it.toFirAnnotationCall(session, javaTypeParameterStack) } }
annotationBuilder = { javaConstructor.convertAnnotationsToFir(session, javaTypeParameterStack) }
for ((index, valueParameter) in javaConstructor.valueParameters.withIndex()) {
valueParameters += valueParameter.toFirValueParameter(
this@JavaSymbolProvider.session, moduleData, index, javaTypeParameterStack,
@@ -554,14 +556,14 @@ class JavaSymbolProvider(
)
override fun getPackage(fqName: FqName): FqName? {
return packageCache.getValue(fqName)
return packageCache.getValue(fqName)?.fqName
}
private fun findPackage(fqName: FqName): FqName? {
private fun findPackage(fqName: FqName): JavaPackage? {
return try {
val facade = KotlinJavaPsiFacade.getInstance(project)
val javaPackage = facade.findPackage(fqName.asString(), searchScope) ?: return null
FqName(javaPackage.qualifiedName)
JavaPackageImpl(javaPackage, searchScope)
} catch (e: ProcessCanceledException) {
return null
}
@@ -65,11 +65,7 @@ internal fun FirTypeRef.toConeKotlinTypeProbablyFlexible(
internal fun JavaType.toFirJavaTypeRef(session: FirSession, javaTypeParameterStack: JavaTypeParameterStack): FirJavaTypeRef {
return buildJavaTypeRef {
annotationBuilder = {
(this@toFirJavaTypeRef as? JavaClassifierType)?.annotations.orEmpty().map {
it.toFirAnnotationCall(session, javaTypeParameterStack)
}
}
annotationBuilder = { convertAnnotationsToFir(session, javaTypeParameterStack) }
type = this@toFirJavaTypeRef
}
}
@@ -89,13 +85,11 @@ private fun JavaType?.toConeKotlinTypeWithoutEnhancement(
session: FirSession, javaTypeParameterStack: JavaTypeParameterStack,
mode: FirJavaTypeConversionMode
): ConeKotlinType {
val attributes = if (this != null && annotations.isNotEmpty()) {
ConeAttributes.create(
listOf(CustomAnnotationTypeAttribute(annotations.map { it.toFirAnnotationCall(session, javaTypeParameterStack) }))
)
} else {
val attributes = if (this != null && annotations.isNotEmpty())
ConeAttributes.create(listOf(CustomAnnotationTypeAttribute(convertAnnotationsToFir(session, javaTypeParameterStack))))
else
ConeAttributes.Empty
}
return when (this) {
is JavaClassifierType ->
toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, mode, attributes)
@@ -148,7 +148,23 @@ private fun buildArgumentMapping(
return buildResolvedArgumentList(mapping)
}
internal fun JavaAnnotation.toFirAnnotationCall(
internal fun Iterable<JavaAnnotation>.convertAnnotationsToFir(
session: FirSession, javaTypeParameterStack: JavaTypeParameterStack
): List<FirAnnotationCall> = map { it.toFirAnnotationCall(session, javaTypeParameterStack) }
internal fun JavaAnnotationOwner.convertAnnotationsToFir(
session: FirSession, javaTypeParameterStack: JavaTypeParameterStack
): List<FirAnnotationCall> = annotations.convertAnnotationsToFir(session, javaTypeParameterStack)
internal fun MutableList<FirAnnotationCall>.addFromJava(
session: FirSession,
javaAnnotationOwner: JavaAnnotationOwner,
javaTypeParameterStack: JavaTypeParameterStack
) {
javaAnnotationOwner.annotations.mapTo(this) { it.toFirAnnotationCall(session, javaTypeParameterStack) }
}
private fun JavaAnnotation.toFirAnnotationCall(
session: FirSession, javaTypeParameterStack: JavaTypeParameterStack
): FirAnnotationCall {
return buildAnnotationCall {
@@ -187,14 +203,6 @@ internal fun JavaAnnotation.toFirAnnotationCall(
}
}
internal fun MutableList<FirAnnotationCall>.addFromJava(
session: FirSession,
javaAnnotationOwner: JavaAnnotationOwner,
javaTypeParameterStack: JavaTypeParameterStack
) {
javaAnnotationOwner.annotations.mapTo(this) { it.toFirAnnotationCall(session, javaTypeParameterStack) }
}
internal fun JavaValueParameter.toFirValueParameter(
session: FirSession, moduleData: FirModuleData, index: Int, javaTypeParameterStack: JavaTypeParameterStack
): FirValueParameter {
@@ -204,7 +212,7 @@ internal fun JavaValueParameter.toFirValueParameter(
name = this@toFirValueParameter.name ?: Name.identifier("p$index")
returnTypeRef = type.toFirJavaTypeRef(session, javaTypeParameterStack)
isVararg = this@toFirValueParameter.isVararg
annotationBuilder = { annotations.map { it.toFirAnnotationCall(session, javaTypeParameterStack) }}
annotationBuilder = { convertAnnotationsToFir(session, javaTypeParameterStack) }
}
}
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.fir.visitors.transformInplace
import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.load.java.structure.JavaPackage
import org.jetbrains.kotlin.name.Name
import kotlin.properties.Delegates
@@ -43,6 +44,7 @@ class FirJavaClass @FirImplementationDetail internal constructor(
override val symbol: FirRegularClassSymbol,
override val superTypeRefs: MutableList<FirTypeRef>,
override val typeParameters: MutableList<FirTypeParameterRef>,
internal val javaPackage: JavaPackage?,
internal val javaTypeParameterStack: JavaTypeParameterStack,
internal val existingNestedClassifierNames: List<Name>
) : FirRegularClass() {
@@ -131,6 +133,7 @@ internal class FirJavaClassBuilder : FirRegularClassBuilder(), FirAnnotationCont
var isTopLevel: Boolean by Delegates.notNull()
var isStatic: Boolean by Delegates.notNull()
var isNotSam: Boolean by Delegates.notNull()
var javaPackage: JavaPackage? = null
lateinit var javaTypeParameterStack: JavaTypeParameterStack
val existingNestedClassifierNames: MutableList<Name> = mutableListOf()
@@ -157,6 +160,7 @@ internal class FirJavaClassBuilder : FirRegularClassBuilder(), FirAnnotationCont
symbol,
superTypeRefs,
typeParameters,
javaPackage,
javaTypeParameterStack,
existingNestedClassifierNames
)
@@ -6,16 +6,28 @@
package org.jetbrains.kotlin.fir.java.enhancement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
import org.jetbrains.kotlin.fir.java.convertAnnotationsToFir
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
import org.jetbrains.kotlin.fir.resolve.symbolProvider
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.load.java.AbstractAnnotationTypeQualifierResolver
import org.jetbrains.kotlin.load.java.JavaModuleAnnotationsProvider
import org.jetbrains.kotlin.load.java.JavaTypeEnhancementState
import org.jetbrains.kotlin.load.java.JavaTypeQualifiersByElementType
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_ANNOTATION_MEMBER_NAME
import org.jetbrains.kotlin.name.FqName
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
class FirAnnotationTypeQualifierResolver(private val session: FirSession) :
AbstractAnnotationTypeQualifierResolver<FirAnnotationCall>(session.javaTypeEnhancementState)
{
class FirAnnotationTypeQualifierResolver(
private val session: FirSession,
javaTypeEnhancementState: JavaTypeEnhancementState,
private val javaModuleAnnotationsProvider: JavaModuleAnnotationsProvider,
) : AbstractAnnotationTypeQualifierResolver<FirAnnotationCall>(javaTypeEnhancementState), FirSessionComponent {
override val FirAnnotationCall.annotations: Iterable<FirAnnotationCall>
get() = coneClassLikeType?.lookupTag?.toSymbol(session)?.fir?.annotations.orEmpty()
@@ -38,4 +50,22 @@ class FirAnnotationTypeQualifierResolver(private val session: FirSession) :
is FirArrayOfCall -> arguments.flatMap { it.toEnumNames() }
else -> listOfNotNull(toResolvedCallableSymbol()?.callableId?.callableName?.asString())
}
fun extractDefaultQualifiers(firClass: FirRegularClass): JavaTypeQualifiersByElementType? {
val classId = firClass.symbol.classId
val outerClassId = classId.outerClassId
val parentQualifiers = if (outerClassId != null) {
(session.symbolProvider.getClassLikeSymbolByFqName(outerClassId)?.fir as? FirRegularClass)
?.let { extractDefaultQualifiers(it) }
} else {
val forModule = javaModuleAnnotationsProvider.getAnnotationsForModuleOwnerOfClass(classId)
?.let { extractAndMergeDefaultQualifiers(null, it.convertAnnotationsToFir(session, JavaTypeParameterStack.EMPTY)) }
val forPackage = (firClass as? FirJavaClass)?.javaPackage
?.let { extractAndMergeDefaultQualifiers(forModule, it.convertAnnotationsToFir(session, JavaTypeParameterStack.EMPTY)) }
forPackage ?: forModule
}
return extractAndMergeDefaultQualifiers(parentQualifiers, firClass.annotations)
}
}
val FirSession.javaAnnotationTypeQualifierResolver: FirAnnotationTypeQualifierResolver by FirSession.sessionComponentAccessor()
@@ -1,18 +0,0 @@
/*
* Copyright 2010-2020 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.java.enhancement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.load.java.JavaTypeEnhancementState
class FirJsr305StateContainer(val javaTypeEnhancementState: JavaTypeEnhancementState) : FirSessionComponent {
companion object {
val Default: FirJsr305StateContainer = FirJsr305StateContainer(JavaTypeEnhancementState.DEFAULT)
}
}
val FirSession.jsr305StateContainer: FirJsr305StateContainer by FirSession.sessionComponentAccessor()
@@ -1,17 +0,0 @@
/*
* Copyright 2010-2021 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.java.enhancement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.load.java.JavaTypeEnhancementState
class FirJavaTypeEnhancementStateComponent(val javaTypeEnhancementState: JavaTypeEnhancementState) : FirSessionComponent
private val FirSession.javaTypeEnhancementStateComponent: FirJavaTypeEnhancementStateComponent by FirSession.sessionComponentAccessor()
val FirSession.javaTypeEnhancementState: JavaTypeEnhancementState
get() = javaTypeEnhancementStateComponent.javaTypeEnhancementState
@@ -62,10 +62,10 @@ class FirSignatureEnhancement(
private val javaTypeParameterStack: JavaTypeParameterStack =
if (owner is FirJavaClass) owner.javaTypeParameterStack else JavaTypeParameterStack.EMPTY
private val typeQualifierResolver = FirAnnotationTypeQualifierResolver(session)
private val typeQualifierResolver = session.javaAnnotationTypeQualifierResolver
private val contextQualifiers: JavaTypeQualifiersByElementType? =
typeQualifierResolver.extractAndMergeDefaultQualifiers(null, owner.annotations)
typeQualifierResolver.extractDefaultQualifiers(owner)
private val enhancements = mutableMapOf<FirCallableSymbol<*>, FirCallableSymbol<*>>()
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.resolve.jvm.modules
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.load.java.lazy.JavaModuleAnnotationsProvider
import org.jetbrains.kotlin.load.java.JavaModuleAnnotationsProvider
import org.jetbrains.kotlin.name.FqName
interface JavaModuleResolver : JavaModuleAnnotationsProvider {
@@ -1,25 +0,0 @@
// ALLOW_KOTLIN_PACKAGE
// JSPECIFY_STATE: strict
// FILE: sandbox/module-info.java
import org.jspecify.nullness.NullMarked;
@NullMarked
module sandbox {
requires java9_annotations;
exports test;
}
// FILE: sandbox/test/Test.java
package test;
public class Test {
public void foo(Integer x) {}
}
// FILE: main.kt
import test.Test
fun main(x: Test) {
x.foo(null)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// ALLOW_KOTLIN_PACKAGE
// JSPECIFY_STATE: strict
@@ -1,31 +0,0 @@
// ALLOW_KOTLIN_PACKAGE
// JSPECIFY_STATE: strict
// FILE: sandbox/module-info.java
import org.jspecify.nullness.NullMarked;
@NullMarked
module sandbox {
requires java9_annotations;
exports test;
}
// FILE: sandbox/test/package-info.java
@NullMarked
package test;
import org.jspecify.nullness.NullMarked;
// FILE: sandbox/test/Test.java
package test;
public class Test {
public void foo(Integer x) {}
}
// FILE: main.kt
import test.Test
fun main(x: Test) {
x.foo(null)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// ALLOW_KOTLIN_PACKAGE
// JSPECIFY_STATE: strict
@@ -1,30 +0,0 @@
// ALLOW_KOTLIN_PACKAGE
// JSPECIFY_STATE: strict
// MODULE: module1
// FILE: module1/module-info.java
module module1 {
}
// MODULE: module2(module1)
// FILE: module2/module-info.java
import org.jspecify.nullness.NullMarked;
@NullMarked
module module2 {
requires java9_annotations;
requires module1;
exports test2;
}
// FILE: module2/test2/Test.java
package test2;
public class Test {
public void foo(Integer x) {}
}
// FILE: main.kt
fun main(y: test2.Test) {
y.foo(null)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// ALLOW_KOTLIN_PACKAGE
// JSPECIFY_STATE: strict
@@ -1,25 +0,0 @@
// ALLOW_KOTLIN_PACKAGE
// JSPECIFY_STATE: strict
// FILE: my.sand.box/module-info.java
import org.jspecify.nullness.NullMarked;
@NullMarked
open module my.sand.box {
requires java9_annotations;
exports my.test;
}
// FILE: my.sand.box/my/test/Test.java
package my.test;
public class Test {
public void foo(Integer x) {}
}
// FILE: main.kt
import my.test.Test
fun main(x: Test) {
x.foo(null)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// ALLOW_KOTLIN_PACKAGE
// JSPECIFY_STATE: strict
@@ -1,45 +0,0 @@
// ALLOW_KOTLIN_PACKAGE
// JSPECIFY_STATE: strict
// MODULE: module1
// FILE: module1/module-info.java
import org.jspecify.nullness.NullMarked;
@NullMarked
module module1 {
requires java9_annotations;
exports test1;
}
// FILE: module1/test1/Test1.java
package test1;
public class Test1 {
public void foo(Integer x) {}
}
// MODULE: module2(module1)
// FILE: module2/module-info.java
module module2 {
requires module1;
exports test2;
}
// FILE: module2/test2/Test2.java
package test2;
import test1.Test1;
public class Test2 extends Test1 {
public void foo2(Integer x) {}
}
// FILE: main.kt
import test1.Test1
import test2.Test2
fun main(x: Test1, y: Test2) {
x.foo(null)
y.foo(null)
y.foo2(null)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// ALLOW_KOTLIN_PACKAGE
// JSPECIFY_STATE: strict
@@ -1,43 +0,0 @@
// ALLOW_KOTLIN_PACKAGE
// JSPECIFY_STATE: strict
// FILE: sandbox/module-info.java
import org.jspecify.nullness.NullMarked;
@NullMarked
module sandbox {
requires java9_annotations;
exports test;
}
// FILE: sandbox/test/Test.java
package test;
public class Test {
public static class Test2 {
public Integer foo(Integer x) { return 1; }
public static class Test4 {
public Integer foo(Integer x) { return 1; }
}
public class Test5 {
public Integer foo(Integer x) { return 1; }
}
}
public class Test3 {
public Integer foo(Integer x) { return 1; }
public class Test5 {
public Integer foo(Integer x) { return 1; }
}
}
}
// FILE: main.kt
import test.Test
fun main(x: Test) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int..kotlin.Int?!")!>x.Test3().foo(null)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int..kotlin.Int?!")!>x.Test3().Test5().foo(null)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int..kotlin.Int?!")!>Test.Test2().foo(null)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int..kotlin.Int?!")!>Test.Test2().Test5().foo(null)<!>
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// ALLOW_KOTLIN_PACKAGE
// JSPECIFY_STATE: strict
@@ -1,39 +0,0 @@
// ALLOW_KOTLIN_PACKAGE
// JSPECIFY_STATE: strict
// MODULE: module1
// FILE: module1/module-info.java
import org.jspecify.nullness.NullMarked;
@NullMarked
module module1 {
requires java9_annotations;
exports test1;
}
// FILE: module1/test1/Test.java
package test1;
public class Test {
public void foo(Integer x) {}
}
// MODULE: module2(module1)
// FILE: module2/module-info.java
module module2 {
requires module1;
exports test2;
}
// FILE: module2/test2/Test.java
package test2;
public class Test {
public void foo(Integer x) {}
}
// FILE: main.kt
fun main(x: test1.Test, y: test2.Test) {
x.foo(null)
y.foo(null)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// ALLOW_KOTLIN_PACKAGE
// JSPECIFY_STATE: strict
@@ -21,5 +21,5 @@ public class Test {
import test.Test
fun main(x: Test) {
x.foo(null)
x.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
}
@@ -27,5 +27,5 @@ public class Test {
import test.Test
fun main(x: Test) {
x.foo(null)
x.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
}
@@ -26,5 +26,5 @@ public class Test {
// FILE: main.kt
fun main(y: test2.Test) {
y.foo(null)
y.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
}
@@ -21,5 +21,5 @@ public class Test {
import my.test.Test
fun main(x: Test) {
x.foo(null)
x.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
}
@@ -39,7 +39,7 @@ import test1.Test1
import test2.Test2
fun main(x: Test1, y: Test2) {
x.foo(null)
y.foo(null)
x.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
y.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
y.foo2(null)
}
@@ -35,9 +35,9 @@ public class Test {
import test.Test
fun main(x: Test) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int..kotlin.Int?!")!>x.Test3().foo(null)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int..kotlin.Int?!")!>x.Test3().Test5().foo(null)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>x.Test3().foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>x.Test3().Test5().foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int..kotlin.Int?!")!>Test.Test2().foo(null)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int..kotlin.Int?!")!>Test.Test2().Test5().foo(null)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>Test.Test2().foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>Test.Test2().Test5().foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)<!>
}
@@ -34,6 +34,6 @@ public class Test {
// FILE: main.kt
fun main(x: test1.Test, y: test2.Test) {
x.foo(null)
x.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
y.foo(null)
}
@@ -162,15 +162,15 @@ fun main(a: A, b: A.B, c: A.C) {
b.baz()!!.get(0)?.get(0)
// c
c.foo("", null)?.length
c.foo("", null)<!UNNECESSARY_SAFE_CALL!>?.<!>length
c.foo("", null).length
c.foo(null, "").length
c.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
c.foobar(null, "")<!UNSAFE_CALL!>.<!>length
c.foobar("", null)?.length
c.bar().length
c.bar()!!.length
c.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
c.field?.length
c.field<!UNSAFE_CALL!>.<!>length
@@ -48,7 +48,7 @@ import test2.A2
fun main(a: A, a2: A2) {
a.foo("", "", null)?.length
a.foo("", "", null).length
a.foo(null, <!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
a.bar().length
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
@@ -68,12 +68,12 @@ public class A {
// FILE: main.kt
fun main(a: test.A) {
a.foo("", null)?.length
a.foo("", null)<!UNNECESSARY_SAFE_CALL!>?.<!>length
a.foo("", null).length
a.foo(null, "").length
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
a.bar().length
a.bar()!!.length
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
a.field?.length
a.field.length
@@ -1,181 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// JSR305_GLOBAL_REPORT: strict
// FILE: NonNullApi.java
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Nonnull
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
public @interface NonNullApi {
}
// FILE: NullableApi.java
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.annotation.CheckForNull;
import javax.annotation.meta.TypeQualifierDefault;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@CheckForNull
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
public @interface NullableApi {
}
// FILE: FieldsAreNullable.java
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.annotation.Nonnull;
import javax.annotation.CheckForNull;
import javax.annotation.meta.TypeQualifierDefault;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@CheckForNull
@TypeQualifierDefault({ElementType.FIELD})
public @interface FieldsAreNullable {
}
// FILE: A.java
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
@NonNullApi
public class A {
public String field = null;
public String foo(String x, @CheckForNull CharSequence y) {
return "";
}
@NullableApi
public String foobar(String x, @NonNullApi CharSequence y) {
return "";
}
public String bar() {
return "";
}
@Nullable
public java.util.List<String> baz() {
return null;
}
@NullableApi
public class B {
public String field = null;
public String foo(String x, @Nonnull CharSequence y) {
return "";
}
@NonNullApi
public String foobar(String x, @NullableApi CharSequence y) {
return "";
}
public String bar() {
return "";
}
@Nullable
public java.util.List<String> baz() {
return null;
}
}
@FieldsAreNullable
public class C {
public String field = null;
public String foo(String x, @Nullable CharSequence y) {
return "";
}
@NullableApi
public String foobar(String x, @Nullable CharSequence y) {
return "";
}
public String bar() {
return "";
}
@Nullable
public java.util.List<String> baz() {
return null;
}
}
}
// FILE: main.kt
fun main(a: A, b: A.B, c: A.C) {
a.foo("", null)<!UNNECESSARY_SAFE_CALL!>?.<!>length
a.foo("", null).length
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
a.foobar(null, "")<!UNSAFE_CALL!>.<!>length
a.foobar("", <!NULL_FOR_NONNULL_TYPE!>null<!>)?.length
a.bar().length
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
a.field<!UNNECESSARY_SAFE_CALL!>?.<!>length
a.field.length
a.baz()<!UNSAFE_CALL!>.<!>get(0)
a.baz()!!.get(0).get(0)
a.baz()!!.get(0)?.get(0)
// b
b.foo("", <!NULL_FOR_NONNULL_TYPE!>null<!>)?.length
b.foo("", <!NULL_FOR_NONNULL_TYPE!>null<!>)<!UNSAFE_CALL!>.<!>length
b.foo(null, "")<!UNSAFE_CALL!>.<!>length
b.foobar(<!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
b.foobar("", null)<!UNNECESSARY_SAFE_CALL!>?.<!>length
b.bar()<!UNSAFE_CALL!>.<!>length
b.bar()!!.length
b.field?.length
b.field<!UNSAFE_CALL!>.<!>length
b.baz()<!UNSAFE_CALL!>.<!>get(0)
b.baz()!!.get(0).get(0)
b.baz()!!.get(0)?.get(0)
// c
c.foo("", null)?.length
c.foo("", null).length
c.foo(null, "").length
c.foobar(null, "")<!UNSAFE_CALL!>.<!>length
c.foobar("", null)?.length
c.bar().length
c.bar()!!.length
c.field?.length
c.field<!UNSAFE_CALL!>.<!>length
c.baz()<!UNSAFE_CALL!>.<!>get(0)
c.baz()!!.get(0).get(0)
c.baz()!!.get(0)?.get(0)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// JSR305_GLOBAL_REPORT: strict
@@ -1,70 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// JSR305_GLOBAL_REPORT: strict
// RENDER_PACKAGE: test, test2
// FILE: test/package-info.java
@javax.annotation.ParametersAreNonnullByDefault()
package test;
// FILE: test/A.java
package test;
import javax.annotation.*;
public class A {
@Nullable public String field = null;
public String foo(String q, @Nonnull String x, @CheckForNull CharSequence y) {
return "";
}
@Nonnull
public String bar() {
return "";
}
}
// FILE: test2/A2.java
package test2;
import javax.annotation.*;
public class A2 {
@Nullable public String field = null;
public String foo(String q, @Nonnull String x, @CheckForNull CharSequence y) {
return "";
}
@Nonnull
public String bar() {
return "";
}
}
// FILE: main.kt
import test.A
import test2.A2
fun main(a: A, a2: A2) {
a.foo("", "", null)?.length
a.foo("", "", null).length
a.foo(null, <!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
a.bar().length
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
a.field?.length
a.field<!UNSAFE_CALL!>.<!>length
a2.foo("", "", null)?.length
a2.foo("", "", null).length
a2.foo(null, <!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
a2.bar().length
a2.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
a2.field?.length
a2.field<!UNSAFE_CALL!>.<!>length
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// JSR305_GLOBAL_REPORT: strict
@@ -1,85 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// JSR305_GLOBAL_REPORT: strict
// RENDER_PACKAGE: test
// FILE: spr/Nullable.java
package spr;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierNickname;
import javax.annotation.meta.When;
@Target({ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Nonnull(when = When.MAYBE)
@TypeQualifierNickname
public @interface Nullable {
}
// FILE: spr/NonNullApi.java
package spr;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
@Target(ElementType.PACKAGE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Nonnull
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})
public @interface NonNullApi {
}
// FILE: test/package-info.java
@spr.NonNullApi()
package test;
// FILE: test/A.java
package test;
import spr.*;
public class A {
public String field = null;
public String foo(String x, @Nullable CharSequence y) {
return "";
}
public String bar() {
return "";
}
@Nullable
public java.util.List<String> baz() {
return null;
}
}
// FILE: main.kt
fun main(a: test.A) {
a.foo("", null)?.length
a.foo("", null).length
a.foo(null, "").length
a.bar().length
a.bar()!!.length
a.field?.length
a.field.length
a.baz()<!UNSAFE_CALL!>.<!>get(0)
a.baz()!!.get(0).get(0)
a.baz()!!.get(0)?.get(0)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// JSR305_GLOBAL_REPORT: strict
// RENDER_PACKAGE: test
@@ -3,7 +3,7 @@
* 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.load.java.lazy
package org.jetbrains.kotlin.load.java
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
import org.jetbrains.kotlin.name.ClassId
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.java.*
import org.jetbrains.kotlin.load.java.JavaModuleAnnotationsProvider
import org.jetbrains.kotlin.load.java.components.JavaPropertyInitializerEvaluator
import org.jetbrains.kotlin.load.java.components.JavaResolverCache
import org.jetbrains.kotlin.load.java.components.SignaturePropagator
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.java.AnnotationTypeQualifierResolver
import org.jetbrains.kotlin.load.java.JavaClassFinder
import org.jetbrains.kotlin.load.java.JavaClassesTracker
import org.jetbrains.kotlin.load.java.JavaModuleAnnotationsProvider
import org.jetbrains.kotlin.load.java.JavaTypeEnhancementState
import org.jetbrains.kotlin.load.java.components.JavaPropertyInitializerEvaluator
import org.jetbrains.kotlin.load.java.components.JavaResolverCache
@@ -55,6 +55,7 @@ import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
@OptIn(PrivateSessionConstructor::class, SessionConfiguration::class)
@@ -91,7 +92,7 @@ internal object FirIdeSessionFactory {
registerIdeComponents(project)
registerCommonComponents(languageVersionSettings)
registerCommonJavaComponents()
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
registerResolveComponents()
val provider = FirIdeProvider(
@@ -193,7 +194,7 @@ internal object FirIdeSessionFactory {
registerIdeComponents(project)
register(FirPhaseManager::class, FirPhaseCheckingPhaseManager)
registerCommonComponents(languageVersionSettings)
registerCommonJavaComponents()
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
registerJavaSpecificResolveComponents()
val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)