diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index a326f077986..0d1d73b41c5 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope +import org.jetbrains.kotlin.fir.symbols.AccessorSymbol import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor @@ -670,7 +671,7 @@ class Fir2IrVisitor( return when (this) { is FirPropertyFromParameterResolvedNamedReference -> IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER is FirResolvedNamedReference -> when (resolvedSymbol) { - is FirAccessorSymbol, is SyntheticPropertySymbol -> IrStatementOrigin.GET_PROPERTY + is AccessorSymbol, is SyntheticPropertySymbol -> IrStatementOrigin.GET_PROPERTY else -> null } else -> null 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 b4c8a6fb456..c869ba96647 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 @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod import org.jetbrains.kotlin.fir.java.declarations.FirJavaValueParameter +import org.jetbrains.kotlin.fir.resolve.calls.possibleGetterNamesByPropertyName import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.ProcessorAction.NEXT @@ -23,10 +24,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirSuperTypeScope import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef -import org.jetbrains.kotlin.load.java.propertyNameByGetMethodName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly -import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeFirstWord class JavaClassUseSiteMemberScope( klass: FirRegularClass, @@ -150,28 +148,16 @@ class JavaClassUseSiteMemberScope( } override fun processPropertiesByName(name: Name, processor: (FirCallableSymbol<*>) -> ProcessorAction): ProcessorAction { - if (name.isSpecial) { + // Do not generate accessors at all? + if (true) { return processAccessorFunctionsAndPropertiesByName(name, emptyList(), null, processor) } - val identifier = name.identifier - val capitalizedAsciiName = identifier.capitalizeAsciiOnly() - val capitalizedFirstWordName = identifier.capitalizeFirstWord(asciiOnly = true) - val getterNames = listOfNotNull( - Name.identifier(GETTER_PREFIX + capitalizedAsciiName), - if (capitalizedFirstWordName == capitalizedAsciiName) null else Name.identifier(GETTER_PREFIX + capitalizedFirstWordName), - name.takeIf { identifier.startsWith(IS_PREFIX) } - ).filter { - propertyNameByGetMethodName(it) == name - } - val setterName = Name.identifier(SETTER_PREFIX + identifier.capitalize()) + val getterNames = possibleGetterNamesByPropertyName(name) + val setterName = Name.identifier(SETTER_PREFIX + name.identifier.capitalize()) return processAccessorFunctionsAndPropertiesByName(name, getterNames, setterName, processor) } companion object { - private const val GETTER_PREFIX = "get" - private const val SETTER_PREFIX = "set" - - private const val IS_PREFIX = "is" } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt index 22a8a4da209..a234b43f4ae 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt @@ -7,20 +7,24 @@ package org.jetbrains.kotlin.fir.resolve.calls import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction -import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl -import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter -import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter -import org.jetbrains.kotlin.fir.declarations.impl.FirPropertyImpl -import org.jetbrains.kotlin.fir.declarations.modality -import org.jetbrains.kotlin.fir.declarations.visibility -import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction -import org.jetbrains.kotlin.fir.symbols.* -import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.fir.symbols.AccessorSymbol +import org.jetbrains.kotlin.fir.symbols.CallableId +import org.jetbrains.kotlin.fir.symbols.SyntheticSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +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.load.java.propertyNameByGetMethodName import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly +import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeFirstWord -class SyntheticPropertySymbol(callableId: CallableId) : FirPropertySymbol(callableId), SyntheticSymbol +class SyntheticPropertySymbol( + callableId: CallableId, + override val accessorId: CallableId +) : FirNamedFunctionSymbol(callableId), AccessorSymbol class FirSyntheticFunctionSymbol( callableId: CallableId @@ -28,13 +32,11 @@ class FirSyntheticFunctionSymbol( class FirSyntheticPropertiesScope( val session: FirSession, - private val baseScope: FirScope, - private val typeCalculator: ReturnTypeCalculator + private val baseScope: FirScope ) : FirScope() { val synthetic: MutableMap, FirVariableSymbol<*>> = mutableMapOf() - private fun checkGetAndCreateSynthetic( name: Name, symbol: FirFunctionSymbol<*>, @@ -45,45 +47,41 @@ class FirSyntheticPropertiesScope( if (fir.typeParameters.isNotEmpty()) return ProcessorAction.NEXT if (fir.valueParameters.isNotEmpty()) return ProcessorAction.NEXT - val synthetic = SyntheticPropertySymbol(CallableId(symbol.callableId.packageName, symbol.callableId.className, name)) + val synthetic = SyntheticPropertySymbol( + accessorId = symbol.callableId, + callableId = CallableId(symbol.callableId.packageName, symbol.callableId.className, name) + ) + synthetic.bind(fir) - val returnTypeRef = typeCalculator.tryCalculateReturnType(fir) - val status = FirDeclarationStatusImpl(fir.visibility, fir.modality).apply { - isExpect = false - isActual = false - isOverride = false - isConst = false - isLateInit = false - } - FirPropertyImpl( - null, - session, - returnTypeRef, - null, - name, - null, - null, - true, - synthetic, - false, - status - ).apply { - resolvePhase = fir.resolvePhase - getter = FirDefaultPropertyGetter(null, this@FirSyntheticPropertiesScope.session, returnTypeRef, fir.visibility) - setter = FirDefaultPropertySetter(null, this@FirSyntheticPropertiesScope.session, returnTypeRef, fir.visibility) - } return processor(synthetic) } override fun processPropertiesByName(name: Name, processor: (FirCallableSymbol<*>) -> ProcessorAction): ProcessorAction { - if (name.isSpecial) return ProcessorAction.NEXT - if (baseScope.processFunctionsByName(Name.guessByFirstCharacter("get${name.identifier.capitalize()}")) { - checkGetAndCreateSynthetic(name, it, processor) - }.stop()) return ProcessorAction.STOP - - if (name.asString().startsWith("is") && baseScope.processFunctionsByName(name) { - checkGetAndCreateSynthetic(name, it, processor) - }.stop()) return ProcessorAction.STOP - return super.processPropertiesByName(name, processor) + val getterNames = possibleGetterNamesByPropertyName(name) + for (getterName in getterNames) { + if (baseScope.processFunctionsByName(getterName) { + checkGetAndCreateSynthetic(name, it, processor) + }.stop() + ) return ProcessorAction.STOP + } + return ProcessorAction.NEXT } -} \ No newline at end of file +} + +fun possibleGetterNamesByPropertyName(name: Name): List { + if (name.isSpecial) return emptyList() + val identifier = name.identifier + val capitalizedAsciiName = identifier.capitalizeAsciiOnly() + val capitalizedFirstWordName = identifier.capitalizeFirstWord(asciiOnly = true) + return listOfNotNull( + Name.identifier(GETTER_PREFIX + capitalizedAsciiName), + if (capitalizedFirstWordName == capitalizedAsciiName) null else Name.identifier(GETTER_PREFIX + capitalizedFirstWordName), + name.takeIf { identifier.startsWith(IS_PREFIX) } + ).filter { + propertyNameByGetMethodName(it) == name + } +} + +private const val GETTER_PREFIX = "get" + +private const val IS_PREFIX = "is" diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerLevels.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerLevels.kt index c847c85015d..180d548d19c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerLevels.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerLevels.kt @@ -16,7 +16,6 @@ import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap -import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorWithJump import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractImportingScope @@ -114,7 +113,10 @@ class MemberScopeTowerLevel( } }.stop() ) return ProcessorAction.STOP - return ProcessorAction.NEXT + val withSynthetic = FirSyntheticPropertiesScope(session, scope) + return withSynthetic.processScopeMembers { symbol -> + output.consumeCandidate(symbol, symbol.dispatchReceiverValue(), implicitExtensionReceiver) + } } override fun > processElementsByName( diff --git a/compiler/fir/resolve/testData/resolve/expresssions/genericDecorator.txt b/compiler/fir/resolve/testData/resolve/expresssions/genericDecorator.txt index 23394588f1f..acb550e6810 100644 --- a/compiler/fir/resolve/testData/resolve/expresssions/genericDecorator.txt +++ b/compiler/fir/resolve/testData/resolve/expresssions/genericDecorator.txt @@ -5,7 +5,7 @@ FILE: test.kt } public final override fun getLookupString(): R|kotlin/String| { - ^getLookupString R|/Decorator.delegate|.R|/LookupElement.lookupString| + ^getLookupString this@R|/Decorator|.R|/Decorator.delegate|.R|/LookupElement.lookupString| } } diff --git a/compiler/fir/resolve/testData/resolve/expresssions/overriddenJavaGetter.txt b/compiler/fir/resolve/testData/resolve/expresssions/overriddenJavaGetter.txt index 78fc2c5ca70..4ddeea411b6 100644 --- a/compiler/fir/resolve/testData/resolve/expresssions/overriddenJavaGetter.txt +++ b/compiler/fir/resolve/testData/resolve/expresssions/overriddenJavaGetter.txt @@ -11,6 +11,6 @@ FILE: Derived.kt } public final fun test(): R|kotlin/Unit| { lval d: R|Derived| = R|/Derived.Derived|() - lval res1: R|ft!| = R|/d|.R|/Base.something| + lval res1: R|kotlin/String| = R|/d|.R|/Derived.something| lval res2: R|kotlin/String| = R|/d|.R|/Derived.getSomething|() } diff --git a/compiler/fir/resolve/testData/resolve/problems/javaAccessorConversion.kt b/compiler/fir/resolve/testData/resolve/problems/javaAccessorConversion.kt index 7a2258723c5..3b9feb647a6 100644 --- a/compiler/fir/resolve/testData/resolve/problems/javaAccessorConversion.kt +++ b/compiler/fir/resolve/testData/resolve/problems/javaAccessorConversion.kt @@ -74,7 +74,7 @@ class Foo { } fun test_4(foo: Foo) { - foo.x // should be error + foo.x // should be error } fun test_5(x: D) { diff --git a/compiler/fir/resolve/testData/resolve/problems/javaAccessorConversion.txt b/compiler/fir/resolve/testData/resolve/problems/javaAccessorConversion.txt index 79d58c33d0e..51482dbde15 100644 --- a/compiler/fir/resolve/testData/resolve/problems/javaAccessorConversion.txt +++ b/compiler/fir/resolve/testData/resolve/problems/javaAccessorConversion.txt @@ -22,7 +22,7 @@ FILE: main.kt } public final fun test_4(foo: R|Foo|): R|kotlin/Unit| { - R|/foo|.# + R|/foo|.R|/Foo.x| } public final fun test_5(x: R|D|): R|kotlin/Unit| { R|/x|.R|/D.isGood| diff --git a/compiler/fir/resolve/testData/resolve/stdlib/j+k/MapEntry.txt b/compiler/fir/resolve/testData/resolve/stdlib/j+k/MapEntry.txt index 61f54feae89..e8e6310b102 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/j+k/MapEntry.txt +++ b/compiler/fir/resolve/testData/resolve/stdlib/j+k/MapEntry.txt @@ -7,7 +7,7 @@ FILE: main.kt } public final fun test(): R|kotlin/Unit| { lval b: R|MyMapEntry| = R|/MyMapEntry.MyMapEntry|() - R|/b|.R|/Test.MapEntryImpl.key| - R|/b|.R|/Test.MapEntryImpl.value| + R|/b|.R|FakeOverride| + R|/b|.R|FakeOverride| R|/b|.R|/Test.MapEntryImpl.setValue|(Null(null)) } diff --git a/compiler/fir/resolve/testData/resolve/stdlib/j+k/SyntheticWithForEach.txt b/compiler/fir/resolve/testData/resolve/stdlib/j+k/SyntheticWithForEach.txt index f087124cb7d..e98dad788f9 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/j+k/SyntheticWithForEach.txt +++ b/compiler/fir/resolve/testData/resolve/stdlib/j+k/SyntheticWithForEach.txt @@ -1,11 +1,11 @@ FILE: test.kt public final fun R|Call|.testForEach(): R|kotlin/Unit| { - R|/Call.arguments|.R|FakeOverride|( = forEach@fun (key: R|kotlin/String!|, value: R|kotlin/String!|): R|kotlin/Unit| { + this@R|/Call|.R|/Call.arguments|.R|FakeOverride|( = forEach@fun (key: R|kotlin/String!|, value: R|kotlin/String!|): R|kotlin/Unit| { R|/key|.R|kotlin/String.length| R|/value|.R|kotlin/String.length| } ) - R|/Call.arguments|.R|kotlin/collections/forEach|!|, R|ft!|>( = forEach@fun (it: R|kotlin/collections/Map.Entry!, ft!>|): R|kotlin/Unit| { + this@R|/Call|.R|/Call.arguments|.R|kotlin/collections/forEach|!|, R|ft!|>( = forEach@fun (it: R|kotlin/collections/Map.Entry!, ft!>|): R|kotlin/Unit| { R|/it|.R|FakeOverride!|>|.R|kotlin/String.length| R|/it|.R|FakeOverride!|>|.R|kotlin/String.length| } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/SyntheticSymbol.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/SyntheticSymbol.kt index b6c2f596d13..d29c788f60a 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/SyntheticSymbol.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/SyntheticSymbol.kt @@ -5,4 +5,9 @@ package org.jetbrains.kotlin.fir.symbols -interface SyntheticSymbol \ No newline at end of file +interface SyntheticSymbol + +interface AccessorSymbol : SyntheticSymbol { + val callableId: CallableId // it's an id of related property (synthetic or not) + val accessorId: CallableId // it's an id of accessor function +} \ No newline at end of file diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirFunctionSymbol.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirFunctionSymbol.kt index 89e02fd23cd..eaa5a3a74fd 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirFunctionSymbol.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirFunctionSymbol.kt @@ -6,8 +6,8 @@ package org.jetbrains.kotlin.fir.symbols.impl import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.symbols.AccessorSymbol import org.jetbrains.kotlin.fir.symbols.CallableId -import org.jetbrains.kotlin.fir.symbols.SyntheticSymbol import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -35,8 +35,8 @@ class FirConstructorSymbol( class FirAccessorSymbol( callableId: CallableId, - val accessorId: CallableId -) : FirFunctionSymbol(callableId), SyntheticSymbol + override val accessorId: CallableId +) : FirFunctionSymbol(callableId), AccessorSymbol // ------------------------ unnamed ------------------------ diff --git a/idea/testData/fir/multiModule/javaInheritsKotlinProperty/jvm/Test.txt b/idea/testData/fir/multiModule/javaInheritsKotlinProperty/jvm/Test.txt index a64cae97643..40592906772 100644 --- a/idea/testData/fir/multiModule/javaInheritsKotlinProperty/jvm/Test.txt +++ b/idea/testData/fir/multiModule/javaInheritsKotlinProperty/jvm/Test.txt @@ -5,7 +5,7 @@ FILE: Test.kt } public final fun test(): R|kotlin/Int| { - ^test R|/Inheritor.x| + ^test this@R|/Base|.R|/Base.x| } }