diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/java/JavaClassRendering.kt b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/java/JavaClassRendering.kt index 77bcfb51648..be017d9a138 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/java/JavaClassRendering.kt +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/java/JavaClassRendering.kt @@ -7,25 +7,21 @@ package org.jetbrains.kotlin.fir.java import org.jetbrains.kotlin.fir.FirRenderer import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass import org.jetbrains.kotlin.fir.java.declarations.FirJavaConstructor import org.jetbrains.kotlin.fir.java.declarations.FirJavaField import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod -import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.buildUseSiteMemberScope -import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope fun renderJavaClass(renderer: FirRenderer, javaClass: FirJavaClass, session: FirSession) { - val enhancementScope = javaClass.buildUseSiteMemberScope(session, ScopeSession()).let { - when (it) { - is FirCompositeScope -> it.scopes.filterIsInstance().first() - is JavaClassEnhancementScope -> it - else -> null - } - } - if (enhancementScope == null) { + val memberScope = javaClass.buildUseSiteMemberScope(session, ScopeSession()) + + val staticScope = javaClass.scopeProvider.getStaticScope(javaClass, session, ScopeSession()) + + if (memberScope == null && staticScope == null) { javaClass.accept(renderer, null) } else { renderer.visitMemberDeclaration(javaClass) @@ -34,8 +30,15 @@ fun renderJavaClass(renderer: FirRenderer, javaClass: FirJavaClass, session: Fir val renderedDeclarations = mutableListOf() for (declaration in javaClass.declarations) { if (declaration in renderedDeclarations) continue + + val scopeToUse = + if (declaration is FirCallableMemberDeclaration<*> && declaration.status.isStatic) + staticScope + else + memberScope + when (declaration) { - is FirJavaConstructor -> enhancementScope.processDeclaredConstructors { symbol -> + is FirJavaConstructor -> scopeToUse!!.processDeclaredConstructors { symbol -> val enhanced = symbol.fir if (enhanced !in renderedDeclarations) { enhanced.accept(renderer, null) @@ -43,7 +46,7 @@ fun renderJavaClass(renderer: FirRenderer, javaClass: FirJavaClass, session: Fir renderedDeclarations += enhanced } } - is FirJavaMethod -> enhancementScope.processFunctionsByName(declaration.name) { symbol -> + is FirJavaMethod -> scopeToUse!!.processFunctionsByName(declaration.name) { symbol -> val enhanced = symbol.fir if (enhanced !in renderedDeclarations) { enhanced.accept(renderer, null) @@ -51,7 +54,7 @@ fun renderJavaClass(renderer: FirRenderer, javaClass: FirJavaClass, session: Fir renderedDeclarations += enhanced } } - is FirJavaField -> enhancementScope.processPropertiesByName(declaration.name) { symbol -> + is FirJavaField -> scopeToUse!!.processPropertiesByName(declaration.name) { symbol -> val enhanced = symbol.fir if (enhanced !in renderedDeclarations) { enhanced.accept(renderer, null) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt index 1b413bd12e0..4bb59b973a2 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt @@ -5,24 +5,21 @@ package org.jetbrains.kotlin.fir.java +import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirClass -import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.declarations.classId +import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass -import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope -import org.jetbrains.kotlin.fir.java.scopes.JavaClassUseSiteMemberScope -import org.jetbrains.kotlin.fir.java.scopes.JavaOverrideChecker +import org.jetbrains.kotlin.fir.java.scopes.* import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScopeProvider import org.jetbrains.kotlin.fir.scopes.FirTypeScope -import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.impl.* import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.ConeClassErrorType +import org.jetbrains.kotlin.utils.DFS +import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult class JavaScopeProvider( val declaredMemberScopeDecorator: ( @@ -45,10 +42,11 @@ class JavaScopeProvider( symbol: FirRegularClassSymbol, scopeSession: ScopeSession, visitedSymbols: MutableSet> - ): JavaClassEnhancementScope { + ): JavaClassMembersEnhancementScope { return scopeSession.getOrBuild(symbol, JAVA_ENHANCEMENT) { - JavaClassEnhancementScope( + JavaClassMembersEnhancementScope( useSiteSession, + symbol, buildUseSiteMemberScopeWithJavaTypes(symbol.fir, useSiteSession, scopeSession, visitedSymbols) ) } @@ -107,24 +105,85 @@ class JavaScopeProvider( useSiteSession: FirSession, scopeSession: ScopeSession ): FirScope? { - if (klass !is FirRegularClass) return null - val enhancementScope = scopeSession.getOrBuild(klass.symbol, JAVA_ENHANCEMENT_FOR_STATIC) { + val scope = getStaticMemberScopeForCallables(klass, useSiteSession, scopeSession, hashSetOf()) ?: return null + return FirOnlyCallablesScope(FirStaticScope(scope)) + } + + private fun getStaticMemberScopeForCallables( + klass: FirClass<*>, + useSiteSession: FirSession, + scopeSession: ScopeSession, + visitedClasses: MutableSet + ): JavaClassStaticEnhancementScope? { + if (klass !is FirJavaClass) return null + if (!visitedClasses.add(klass)) return null + + return scopeSession.getOrBuild(klass.symbol, JAVA_ENHANCEMENT_FOR_STATIC) { val declaredScope = buildDeclaredMemberScope(klass) val wrappedDeclaredScope = declaredMemberScopeDecorator(klass, declaredScope, useSiteSession, scopeSession) - JavaClassEnhancementScope( - useSiteSession, JavaClassUseSiteMemberScope( - klass, useSiteSession, - superTypesScope = object : FirTypeScope() { - override fun processOverriddenFunctions( - functionSymbol: FirFunctionSymbol<*>, - processor: (FirFunctionSymbol<*>) -> ProcessorAction - ): ProcessorAction = ProcessorAction.STOP - }, - declaredMemberScope = wrappedDeclaredScope + + val superClassScope = klass.findJavaSuperClass()?.let { + (it.scopeProvider as? JavaScopeProvider) + ?.getStaticMemberScopeForCallables(it, useSiteSession, scopeSession, visitedClasses) + } ?: FirTypeScope.Empty + + val superTypesScopes = klass.findClosestJavaSuperTypes().mapNotNull { + (it.scopeProvider as? JavaScopeProvider) + ?.getStaticMemberScopeForCallables(it, useSiteSession, scopeSession, visitedClasses) + } + + JavaClassStaticEnhancementScope( + useSiteSession, + klass.symbol, + JavaClassStaticUseSiteScope( + useSiteSession, + declaredMemberScope = wrappedDeclaredScope, + superClassScope, superTypesScopes, + klass.javaTypeParameterStack ) ) + }.also { + visitedClasses.remove(klass) } - return FirOnlyCallablesScope(FirStaticScope(enhancementScope)) + } + + private tailrec fun FirRegularClass.findJavaSuperClass(): FirRegularClass? { + val superClass = superConeTypes.firstNotNullResult { + (it.lookupTag.toSymbol(session)?.fir as? FirRegularClass)?.takeIf { superClass -> + superClass.classKind == ClassKind.CLASS + } + } ?: return null + + if (superClass.origin is FirDeclarationOrigin.Java) return superClass + + return superClass.findJavaSuperClass() + } + + private fun FirRegularClass.findClosestJavaSuperTypes(): Collection { + val result = mutableListOf() + DFS.dfs(listOf(this), + { regularClass -> + regularClass.superConeTypes.mapNotNull { + it.lookupTag.toSymbol(session)?.fir as? FirRegularClass + } + }, + object : DFS.AbstractNodeHandler() { + override fun beforeChildren(current: FirRegularClass?): Boolean { + if (this@findClosestJavaSuperTypes === current) return true + if (current is FirJavaClass) { + result.add(current) + return false + } + + return true + } + + override fun result() {} + + } + ) + + return result } override fun getNestedClassifierScope(klass: FirClass<*>, useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? { @@ -136,6 +195,6 @@ class JavaScopeProvider( } } -private val JAVA_ENHANCEMENT_FOR_STATIC = scopeSessionKey() -private val JAVA_ENHANCEMENT = scopeSessionKey() +private val JAVA_ENHANCEMENT_FOR_STATIC = scopeSessionKey() +private val JAVA_ENHANCEMENT = scopeSessionKey() private val JAVA_USE_SITE = scopeSessionKey() diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassEnhancementScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt similarity index 83% rename from compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassEnhancementScope.kt rename to compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt index 50f7ab74a15..073c2b3e144 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassEnhancementScope.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt @@ -1,9 +1,9 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.scopes +package org.jetbrains.kotlin.fir.java.enhancement import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.FirAnnotationContainer @@ -21,11 +21,7 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack import org.jetbrains.kotlin.fir.java.declarations.* -import org.jetbrains.kotlin.fir.java.enhancement.* import org.jetbrains.kotlin.fir.render -import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor -import org.jetbrains.kotlin.fir.scopes.FirTypeScope -import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptor import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.impl.* @@ -40,12 +36,11 @@ import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.Jsr305State -class JavaClassEnhancementScope( +class FirSignatureEnhancement( + private val owner: FirRegularClass, private val session: FirSession, - private val useSiteMemberScope: JavaClassUseSiteMemberScope -) : FirTypeScope() { - private val owner: FirRegularClass = useSiteMemberScope.symbol.fir - + private val overridden: FirSimpleFunction.() -> List> +) { private val javaTypeParameterStack: JavaTypeParameterStack = if (owner is FirJavaClass) owner.javaTypeParameterStack else JavaTypeParameterStack.EMPTY @@ -57,30 +52,16 @@ class JavaClassEnhancementScope( FirJavaEnhancementContext(session) { null }.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, jsr305State, owner.annotations) private val enhancements = mutableMapOf, FirCallableSymbol<*>>() - private val overriddenFunctions = mutableMapOf, Collection>>() - override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) { - useSiteMemberScope.processPropertiesByName(name) process@{ original -> - - val field = enhancements.getOrPut(original) { enhance(original, name) } - processor(field as FirVariableSymbol<*>) - } - - return super.processPropertiesByName(name, processor) + fun enhancedFunction( + function: FirFunctionSymbol<*>, + name: Name? + ): FirFunctionSymbol<*> { + return enhancements.getOrPut(function) { enhance(function, name) } as FirFunctionSymbol<*> } - override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) { - useSiteMemberScope.processFunctionsByName(name) process@{ original -> - - val function = enhancements.getOrPut(original) { enhance(original, name) } - processor(function as FirFunctionSymbol<*>) - } - - return super.processFunctionsByName(name, processor) - } - - override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) { - useSiteMemberScope.processClassifiersByNameWithSubstitution(name, processor) + fun enhancedProperty(property: FirVariableSymbol<*>, name: Name): FirVariableSymbol<*> { + return enhancements.getOrPut(property) { enhance(property, name) } as FirVariableSymbol<*> } private fun enhance( @@ -107,7 +88,7 @@ class JavaClassEnhancementScope( val symbol = FirFieldSymbol(original.callableId) buildJavaField { source = firElement.source - session = this@JavaClassEnhancementScope.session + session = this@FirSignatureEnhancement.session this.symbol = symbol this.name = name visibility = firElement.visibility @@ -126,7 +107,7 @@ class JavaClassEnhancementScope( firElement.getter.delegate, accessorSymbol.accessorId, accessorSymbol.accessorId.callableName ) return buildSyntheticProperty { - session = this@JavaClassEnhancementScope.session + session = this@FirSignatureEnhancement.session this.name = name symbol = FirAccessorSymbol(accessorSymbol.callableId, accessorSymbol.accessorId) delegateGetter = enhancedFunctionSymbol.fir as FirSimpleFunction @@ -150,7 +131,7 @@ class JavaClassEnhancementScope( } return enhanceMethod(firMethod, original.callableId, name) } - + private fun enhanceMethod( firMethod: FirFunction<*>, methodId: CallableId, @@ -169,7 +150,7 @@ class JavaClassEnhancementScope( } } - val overriddenMembers = (firMethod as? FirSimpleFunction)?.overriddenMembers().orEmpty() + val overriddenMembers = (firMethod as? FirSimpleFunction)?.overridden().orEmpty() val hasReceiver = overriddenMembers.any { it.receiverTypeRef != null } val newReceiverTypeRef = if (firMethod is FirJavaMethod && hasReceiver) { @@ -196,7 +177,7 @@ class JavaClassEnhancementScope( val (newTypeRef, newDefaultValue) = newInfo buildValueParameter { source = valueParameter.source - session = this@JavaClassEnhancementScope.session + session = this@FirSignatureEnhancement.session origin = FirDeclarationOrigin.Enhancement returnTypeRef = newTypeRef this.name = valueParameter.name @@ -230,7 +211,7 @@ class JavaClassEnhancementScope( } }.apply { source = firMethod.source - session = this@JavaClassEnhancementScope.session + session = this@FirSignatureEnhancement.session resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES origin = FirDeclarationOrigin.Enhancement this.valueParameters += newValueParameters @@ -240,7 +221,7 @@ class JavaClassEnhancementScope( is FirJavaMethod -> { FirSimpleFunctionBuilder().apply { source = firMethod.source - session = this@JavaClassEnhancementScope.session + session = this@FirSignatureEnhancement.session origin = FirDeclarationOrigin.Enhancement returnTypeRef = newReturnTypeRef receiverTypeRef = newReceiverTypeRef @@ -255,12 +236,12 @@ class JavaClassEnhancementScope( else -> throw AssertionError("Unknown Java method to enhance: ${firMethod.render()}") }.apply { annotations += firMethod.annotations - }.build().also { - overriddenFunctions[it.symbol] = overriddenMembers.mapNotNull { it.symbol as? FirFunctionSymbol<*> } - } + }.build() + return function.symbol } + // ================================================================================================ private fun enhanceReceiverType( @@ -327,17 +308,6 @@ class JavaClassEnhancementScope( private val overrideBindCache = mutableMapOf?, List>>>() - private fun FirSimpleFunction.overriddenMembers(): List> { - val backMap = overrideBindCache.getOrPut(this.name) { - useSiteMemberScope.bindOverrides(this.name) - useSiteMemberScope - .overrideByBase - .toList() - .groupBy({ (_, key) -> key }, { (value) -> value }) - } - return backMap[this.symbol]?.map { it.fir as FirCallableMemberDeclaration<*> } ?: emptyList() - } - private sealed class TypeInSignature { abstract fun getTypeRef(member: FirCallableMemberDeclaration<*>): FirTypeRef @@ -406,18 +376,4 @@ class JavaClassEnhancementScope( containerApplicabilityType ) } - - override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) { - - useSiteMemberScope.processDeclaredConstructors process@{ original -> - - val function = enhancements.getOrPut(original) { enhance(original, name = null) } - processor(function as FirConstructorSymbol) - } - } - - override fun processOverriddenFunctions( - functionSymbol: FirFunctionSymbol<*>, - processor: (FirFunctionSymbol<*>) -> ProcessorAction - ): ProcessorAction = doProcessOverriddenFunctions(functionSymbol, processor, overriddenFunctions, useSiteMemberScope) } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassMembersEnhancementScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassMembersEnhancementScope.kt new file mode 100644 index 00000000000..c9749e300cb --- /dev/null +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassMembersEnhancementScope.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2010-2019 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.scopes + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.java.enhancement.FirSignatureEnhancement +import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor +import org.jetbrains.kotlin.fir.scopes.FirTypeScope +import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.name.Name + +class JavaClassMembersEnhancementScope( + session: FirSession, + owner: FirRegularClassSymbol, + private val useSiteMemberScope: JavaClassUseSiteMemberScope, +) : FirTypeScope() { + private val overriddenFunctions = mutableMapOf, Collection>>() + + private val overrideBindCache = mutableMapOf?, List>>>() + private val signatureEnhancement = FirSignatureEnhancement(owner.fir, session) { + overriddenMembers() + } + + override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) { + useSiteMemberScope.processPropertiesByName(name) process@{ original -> + processor(signatureEnhancement.enhancedProperty(original, name)) + } + + return super.processPropertiesByName(name, processor) + } + + override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) { + useSiteMemberScope.processFunctionsByName(name) process@{ original -> + val enhancedFunction = signatureEnhancement.enhancedFunction(original, name) + + overriddenFunctions[enhancedFunction] = + (enhancedFunction.fir as? FirSimpleFunction) + ?.overriddenMembers() + ?.mapNotNull { it.symbol as? FirFunctionSymbol<*> } + .orEmpty() + + processor(enhancedFunction) + } + + return super.processFunctionsByName(name, processor) + } + + private fun FirSimpleFunction.overriddenMembers(): List> { + val backMap = overrideBindCache.getOrPut(this.name) { + useSiteMemberScope.bindOverrides(this.name) + useSiteMemberScope + .overrideByBase + .toList() + .groupBy({ (_, key) -> key }, { (value) -> value }) + } + return backMap[this.symbol]?.map { it.fir as FirCallableMemberDeclaration<*> } ?: emptyList() + } + + override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) { + useSiteMemberScope.processClassifiersByNameWithSubstitution(name, processor) + } + + override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) { + useSiteMemberScope.processDeclaredConstructors process@{ original -> + val function = signatureEnhancement.enhancedFunction(original, name = null) + processor(function as FirConstructorSymbol) + } + } + + override fun processOverriddenFunctions( + functionSymbol: FirFunctionSymbol<*>, + processor: (FirFunctionSymbol<*>) -> ProcessorAction + ): ProcessorAction = doProcessOverriddenFunctions(functionSymbol, processor, overriddenFunctions, useSiteMemberScope) +} diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassStaticEnhancementScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassStaticEnhancementScope.kt new file mode 100644 index 00000000000..2d5e310a602 --- /dev/null +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassStaticEnhancementScope.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2019 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.scopes + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.java.enhancement.FirSignatureEnhancement +import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.name.Name + +class JavaClassStaticEnhancementScope( + session: FirSession, + owner: FirRegularClassSymbol, + private val useSiteStaticScope: FirScope, +) : FirScope() { + private val signatureEnhancement = FirSignatureEnhancement(owner.fir, session) { + emptyList() + } + + override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) { + useSiteStaticScope.processPropertiesByName(name) process@{ original -> + processor(signatureEnhancement.enhancedProperty(original, name)) + } + + return super.processPropertiesByName(name, processor) + } + + override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) { + useSiteStaticScope.processFunctionsByName(name) process@{ original -> + val enhancedFunction = signatureEnhancement.enhancedFunction(original, name) + processor(enhancedFunction) + } + + return super.processFunctionsByName(name, processor) + } + + override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) { + useSiteStaticScope.processClassifiersByNameWithSubstitution(name, processor) + } + + override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) { + useSiteStaticScope.processDeclaredConstructors process@{ original -> + val function = signatureEnhancement.enhancedFunction(original, name = null) + processor(function as FirConstructorSymbol) + } + } +} diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassStaticUseSiteScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassStaticUseSiteScope.kt new file mode 100644 index 00000000000..1890832efde --- /dev/null +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassStaticUseSiteScope.kt @@ -0,0 +1,82 @@ +/* + * Copyright 2010-2019 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.scopes + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.isStatic +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.addIfNotNull + +class JavaClassStaticUseSiteScope internal constructor( + session: FirSession, + private val declaredMemberScope: FirScope, + private val superClassScope: FirScope, + private val superTypesScopes: List, + javaTypeParameterStack: JavaTypeParameterStack, +) : FirScope() { + private val functions = hashMapOf>>() + private val properties = hashMapOf>>() + private val overrideChecker = JavaOverrideChecker(session, javaTypeParameterStack) + + override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) { + functions.getOrPut(name) { + computeFunctions(name) + }.forEach(processor) + } + + private fun computeFunctions(name: Name): MutableList { + val superClassSymbols = mutableListOf() + superClassScope.processFunctionsByName(name) { + superClassSymbols.addIfNotNull(it as? FirNamedFunctionSymbol) + } + + val result = mutableListOf() + + declaredMemberScope.processFunctionsByName(name) l@{ functionSymbol -> + if (functionSymbol !is FirNamedFunctionSymbol || !functionSymbol.isStatic) return@l + + result.add(functionSymbol) + superClassSymbols.removeAll { superClassSymbol -> + overrideChecker.isOverriddenFunction(functionSymbol.fir, superClassSymbol.fir) + } + } + + result += superClassSymbols + + return result + } + + override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) { + return properties.getOrPut(name) { + computeProperties(name) + }.forEach(processor) + + } + + private fun computeProperties(name: Name): MutableList> { + val result: MutableList> = mutableListOf() + declaredMemberScope.processPropertiesByName(name) l@{ propertySymbol -> + if (!propertySymbol.isStatic) return@l + result.add(propertySymbol) + } + + if (result.isNotEmpty()) return result + + for (superTypesScope in superTypesScopes) { + superTypesScope.processPropertiesByName(name) l@{ propertySymbol -> + if (!propertySymbol.isStatic) return@l + result.add(propertySymbol) + } + } + + return result + } +} diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt index 4e1dd69c5fe..7656e307673 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt @@ -15,8 +15,8 @@ import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack import org.jetbrains.kotlin.fir.java.declarations.* import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticPropertiesScope import org.jetbrains.kotlin.fir.scopes.FirScope -import org.jetbrains.kotlin.fir.scopes.impl.AbstractFirUseSiteMemberScope import org.jetbrains.kotlin.fir.scopes.FirTypeScope +import org.jetbrains.kotlin.fir.scopes.impl.AbstractFirUseSiteMemberScope import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef @@ -81,12 +81,12 @@ class JavaClassUseSiteMemberScope( private fun processAccessorFunctionsAndPropertiesByName( propertyName: Name, getterNames: List, - setterName: Name?, processor: (FirVariableSymbol<*>) -> Unit ) { val overrideCandidates = mutableSetOf>() val klass = symbol.fir declaredMemberScope.processPropertiesByName(propertyName) { variableSymbol -> + if (variableSymbol.isStatic) return@processPropertiesByName overrideCandidates += variableSymbol processor(variableSymbol) } @@ -106,14 +106,9 @@ class JavaClassUseSiteMemberScope( } superTypesScope.processPropertiesByName(propertyName) { - val firCallableMember = it.fir as? FirCallableMemberDeclaration<*> - if (firCallableMember?.isStatic == true) { - processor(it) - } else { - when (val overriddenBy = it.getOverridden(overrideCandidates)) { - null -> processor(it) - is FirAccessorSymbol -> processor(overriddenBy) - } + when (val overriddenBy = it.getOverridden(overrideCandidates)) { + null -> processor(it) + is FirAccessorSymbol -> processor(overriddenBy) } } } @@ -146,11 +141,11 @@ class JavaClassUseSiteMemberScope( override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) { // Do not generate accessors at all? if (name.isSpecial) { - return processAccessorFunctionsAndPropertiesByName(name, emptyList(), null, processor) + return processAccessorFunctionsAndPropertiesByName(name, emptyList(), processor) } val getterNames = FirSyntheticPropertiesScope.possibleGetterNamesByPropertyName(name) val setterName = Name.identifier(SETTER_PREFIX + name.identifier.capitalize()) - return processAccessorFunctionsAndPropertiesByName(name, getterNames, setterName, processor) + return processAccessorFunctionsAndPropertiesByName(name, getterNames, processor) } companion object { diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaOverrideChecker.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaOverrideChecker.kt index 55a40ced65f..e7940ac14ef 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaOverrideChecker.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaOverrideChecker.kt @@ -69,6 +69,7 @@ class JavaOverrideChecker internal constructor( } override fun isOverriddenFunction(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean { + if (overrideCandidate.isStatic != baseDeclaration.isStatic) return false // NB: overrideCandidate is from Java and has no receiver val receiverTypeRef = baseDeclaration.receiverTypeRef val baseParameterTypes = listOfNotNull(receiverTypeRef) + baseDeclaration.valueParameters.map { it.returnTypeRef } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirUseSiteMemberScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirUseSiteMemberScope.kt index 3b2135bcebe..f30583768ec 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirUseSiteMemberScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirUseSiteMemberScope.kt @@ -14,9 +14,9 @@ import org.jetbrains.kotlin.fir.declarations.builder.FirSimpleFunctionBuilder import org.jetbrains.kotlin.fir.declarations.builder.FirValueParameterBuilder import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor -import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.name.Name @@ -44,6 +44,7 @@ abstract class AbstractFirUseSiteMemberScope( ): Collection> = mutableListOf>().apply { val overrideCandidates = mutableSetOf>() declaredMemberScope.processFunctionsByName(name) { + if (it.isStatic) return@processFunctionsByName val directOverridden = computeDirectOverridden(it) this@AbstractFirUseSiteMemberScope.directOverridden[it] = directOverridden val symbol = processInheritedDefaultParameters(it, directOverridden) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassUseSiteMemberScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassUseSiteMemberScope.kt index fba6eb761b0..e3c27ab7b2c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassUseSiteMemberScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassUseSiteMemberScope.kt @@ -6,9 +6,10 @@ package org.jetbrains.kotlin.fir.scopes.impl import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.isStatic import org.jetbrains.kotlin.name.Name class FirClassUseSiteMemberScope( @@ -19,7 +20,8 @@ class FirClassUseSiteMemberScope( override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) { val seen = mutableSetOf>() - declaredMemberScope.processPropertiesByName(name) { + declaredMemberScope.processPropertiesByName(name) l@{ + if (it.isStatic) return@l seen += it processor(it) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirTypeScope.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirTypeScope.kt index 2a4744d704c..09b97b4aa69 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirTypeScope.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirTypeScope.kt @@ -36,4 +36,11 @@ abstract class FirTypeScope : FirScope() { return baseScope.processOverriddenFunctions(functionSymbol, processor) } + + object Empty : FirTypeScope() { + override fun processOverriddenFunctions( + functionSymbol: FirFunctionSymbol<*>, + processor: (FirFunctionSymbol<*>) -> ProcessorAction + ): ProcessorAction = ProcessorAction.NEXT + } } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirCallableSymbol.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirCallableSymbol.kt index 59db65d5274..edb9a480d44 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirCallableSymbol.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirCallableSymbol.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.symbols.impl import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration +import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.CallableId @@ -16,6 +17,8 @@ abstract class FirCallableSymbol> : AbstractFirBas get() = null } +val FirCallableSymbol<*>.isStatic: Boolean get() = (fir as? FirMemberDeclaration)?.status?.isStatic == true + inline fun > E.unwrapSubstitutionOverrides(): E { var current = this while (current.overriddenSymbol != null) { diff --git a/compiler/testData/diagnostics/tests/j+k/inheritanceStaticMethodFromInterface.fir.kt b/compiler/testData/diagnostics/tests/j+k/inheritanceStaticMethodFromInterface.fir.kt index f3b6b2f97a2..28d47637209 100644 --- a/compiler/testData/diagnostics/tests/j+k/inheritanceStaticMethodFromInterface.fir.kt +++ b/compiler/testData/diagnostics/tests/j+k/inheritanceStaticMethodFromInterface.fir.kt @@ -22,7 +22,7 @@ fun main() { C.a C.b - C.foo() + C.foo() C.bar() K.a diff --git a/compiler/testData/diagnostics/testsWithStdLib/resolve/samAgainstFunctionalType.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/resolve/samAgainstFunctionalType.fir.kt index ba53fff0680..09ff515b7d4 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/resolve/samAgainstFunctionalType.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/resolve/samAgainstFunctionalType.fir.kt @@ -26,5 +26,5 @@ public class StaticOverrides { fun test() { StaticOverrides.A.foo {} checkType { _() } StaticOverrides.B.foo {} checkType { _() } - StaticOverrides.C.foo {} checkType { _() } -} \ No newline at end of file + StaticOverrides.C.foo {} checkType { _() } +} diff --git a/compiler/testData/ir/irText/classes/fakeOverridesForJavaStaticMembers.fir.txt b/compiler/testData/ir/irText/classes/fakeOverridesForJavaStaticMembers.fir.txt index 90b41ee34fc..d287a433f45 100644 --- a/compiler/testData/ir/irText/classes/fakeOverridesForJavaStaticMembers.fir.txt +++ b/compiler/testData/ir/irText/classes/fakeOverridesForJavaStaticMembers.fir.txt @@ -5,12 +5,6 @@ FILE fqName: fileName:/fakeOverridesForJavaStaticMembers.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in a.Base' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Test modality:FINAL visibility:public superTypes:[a.Base]' - FUN FAKE_OVERRIDE name:publicStaticMethod visibility:public modality:OPEN <> () returnType:kotlin.Unit [fake_override] - overridden: - public open fun publicStaticMethod (): kotlin.Unit declared in a.Base - FUN FAKE_OVERRIDE name:protectedStaticMethod visibility:protected/*protected static*/ modality:OPEN <> () returnType:kotlin.Unit [fake_override] - overridden: - protected/*protected static*/ open fun protectedStaticMethod (): kotlin.Unit declared in a.Base FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any