diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index b9b2fab1487..e0e3c9d8b12 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -1320,7 +1320,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { parameter("symbol") } - val DECLARATION_CANT_BE_INLINED by error(PositioningStrategy.DECLARATION_SIGNATURE) + val DECLARATION_CANT_BE_INLINED by error(PositioningStrategy.INLINE_FUN_MODIFIER) val OVERRIDE_BY_INLINE by warning(PositioningStrategy.DECLARATION_SIGNATURE) diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/model/RegularDiagnosticData.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/model/RegularDiagnosticData.kt index be7002dc3bd..ab7b36060fe 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/model/RegularDiagnosticData.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/model/RegularDiagnosticData.kt @@ -112,6 +112,7 @@ enum class PositioningStrategy(private val strategy: String? = null) { IMPORT_ALIAS, DECLARATION_START_TO_NAME, REDUNDANT_NULLABLE, + INLINE_FUN_MODIFIER, ; diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index fc2dc640399..793fe1b9d63 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -689,7 +689,7 @@ object FirErrors { val PROTECTED_CALL_FROM_PUBLIC_INLINE by warning2, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) val PRIVATE_CLASS_MEMBER_FROM_INLINE by error2, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) val SUPER_CALL_FROM_PUBLIC_INLINE by error1>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) - val DECLARATION_CANT_BE_INLINED by error0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) + val DECLARATION_CANT_BE_INLINED by error0(SourceElementPositioningStrategies.INLINE_FUN_MODIFIER) val OVERRIDE_BY_INLINE by warning0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val NON_INTERNAL_PUBLISHED_API by error0() val INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE by error2() diff --git a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt index b8d1a430eb3..7550e608ab6 100644 --- a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt +++ b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt @@ -15,8 +15,7 @@ import org.jetbrains.kotlin.KtNodeType import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.lexer.KtTokens.MODALITY_MODIFIERS -import org.jetbrains.kotlin.lexer.KtTokens.VISIBILITY_MODIFIERS +import org.jetbrains.kotlin.lexer.KtTokens.* import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType import org.jetbrains.kotlin.psi.stubs.elements.KtStringTemplateExpressionElementType @@ -339,18 +338,33 @@ object LightTreePositioningStrategies { false } - private class ModifierSetBasedLightTreePositioningStrategy(private val modifierSet: TokenSet) : LightTreePositioningStrategy() { + private open class ModifierSetBasedLightTreePositioningStrategy(private val modifierSet: TokenSet) : LightTreePositioningStrategy() { + protected fun markModifier( + node: LighterASTNode?, + startOffset: Int, + endOffset: Int, + tree: FlyweightCapableTreeStructure, + baseNode: LighterASTNode + ): List? { + if (node == null) return null + val modifierList = tree.modifierList(node) + if (modifierList != null) { + tree.findChildByType(modifierList, modifierSet)?.let { + return markElement(it, startOffset, endOffset, tree, baseNode) + } + } + return null + } + override fun mark( node: LighterASTNode, startOffset: Int, endOffset: Int, tree: FlyweightCapableTreeStructure ): List { - val modifierList = tree.modifierList(node) - if (modifierList != null) { - tree.findChildByType(modifierList, modifierSet)?.let { - return markElement(it, startOffset, endOffset, tree, node) - } + val modifierListRange = markModifier(node, startOffset, endOffset, tree, node) + if (modifierListRange != null) { + return modifierListRange } tree.nameIdentifier(node)?.let { return markElement(it, startOffset, endOffset, tree, node) @@ -367,6 +381,22 @@ object LightTreePositioningStrategies { } } + private class InlineFunLightTreePositioningStrategy : ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(INLINE_KEYWORD)) { + override fun mark( + node: LighterASTNode, + startOffset: Int, + endOffset: Int, + tree: FlyweightCapableTreeStructure + ): List { + if (node.tokenType == KtNodeTypes.PROPERTY) { + return markModifier(tree.getter(node), startOffset, endOffset, tree, node) + ?: markModifier(tree.setter(node), startOffset, endOffset, tree, node) + ?: super.mark(node, startOffset, endOffset, tree) + } + return super.mark(node, startOffset, endOffset, tree) + } + } + val VISIBILITY_MODIFIER: LightTreePositioningStrategy = ModifierSetBasedLightTreePositioningStrategy(VISIBILITY_MODIFIERS) val MODALITY_MODIFIER: LightTreePositioningStrategy = ModifierSetBasedLightTreePositioningStrategy(MODALITY_MODIFIERS) @@ -402,7 +432,7 @@ object LightTreePositioningStrategies { ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.SUSPEND_KEYWORD, KtTokens.FUN_KEYWORD)) val INLINE_OR_VALUE_MODIFIER: LightTreePositioningStrategy = - ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.INLINE_KEYWORD, KtTokens.VALUE_KEYWORD)) + ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(INLINE_KEYWORD, KtTokens.VALUE_KEYWORD)) val INNER_MODIFIER: LightTreePositioningStrategy = ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.INNER_KEYWORD)) @@ -442,6 +472,8 @@ object LightTreePositioningStrategies { val INLINE_PARAMETER_MODIFIER: LightTreePositioningStrategy = ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.NOINLINE_KEYWORD, KtTokens.CROSSINLINE_KEYWORD)) + val INLINE_FUN_MODIFIER: LightTreePositioningStrategy = InlineFunLightTreePositioningStrategy() + val OPERATOR: LightTreePositioningStrategy = object : LightTreePositioningStrategy() { override fun mark( node: LighterASTNode, @@ -1222,7 +1254,7 @@ fun FlyweightCapableTreeStructure.overrideModifier(declaration: modifierList(declaration)?.let { findChildByType(it, KtTokens.OVERRIDE_KEYWORD) } fun FlyweightCapableTreeStructure.inlineModifier(declaration: LighterASTNode): LighterASTNode? = - modifierList(declaration)?.let { findChildByType(it, KtTokens.INLINE_KEYWORD) } + modifierList(declaration)?.let { findChildByType(it, INLINE_KEYWORD) } fun FlyweightCapableTreeStructure.typeParametersList(declaration: LighterASTNode): LighterASTNode? = findChildByType(declaration, KtNodeTypes.TYPE_PARAMETER_LIST) @@ -1241,6 +1273,22 @@ fun FlyweightCapableTreeStructure.userType(node: LighterASTNode) private fun FlyweightCapableTreeStructure.supertypesList(node: LighterASTNode): LighterASTNode? = findChildByType(node, KtNodeTypes.SUPER_TYPE_LIST) +private fun FlyweightCapableTreeStructure.getter(node: LighterASTNode): LighterASTNode? { + val childrenRef = Ref>() + getChildren(node, childrenRef) + return childrenRef.get()?.firstOrNull { + it != null && it.tokenType == KtNodeTypes.PROPERTY_ACCESSOR && findChildByType(it, GET_KEYWORD) != null + } +} + +private fun FlyweightCapableTreeStructure.setter(node: LighterASTNode): LighterASTNode? { + val childrenRef = Ref>() + getChildren(node, childrenRef) + return childrenRef.get()?.firstOrNull { + it != null && it.tokenType == KtNodeTypes.PROPERTY_ACCESSOR && findChildByType(it, SET_KEYWORD) != null + } +} + private fun FlyweightCapableTreeStructure.accessorNamePlaceholder(node: LighterASTNode): LighterASTNode = findChildByType(node, KtTokens.GET_KEYWORD) ?: findChildByType(node, KtTokens.SET_KEYWORD)!! diff --git a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index eaeb59a11b6..8fce2595260 100644 --- a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -399,12 +399,15 @@ object PositioningStrategies { } } - private class ModifierSetBasedPositioningStrategy(private val modifierSet: TokenSet) : PositioningStrategy() { - override fun mark(element: KtModifierListOwner): List { - val modifierList = element.modifierList + private open class ModifierSetBasedPositioningStrategy(private val modifierSet: TokenSet) : PositioningStrategy() { + protected fun markModifier(element: KtModifierListOwner?): List? = + modifierSet.types.mapNotNull { + element?.modifierList?.getModifier(it as KtModifierKeywordToken)?.textRange + }.takeIf { it.isNotEmpty() } - val result = modifierSet.types.mapNotNull { modifierList?.getModifier(it as KtModifierKeywordToken)?.textRange } - if (result.isNotEmpty()) return result + override fun mark(element: KtModifierListOwner): List { + val result = markModifier(element) + if (result != null) return result // Try to resolve situation when there's no visibility modifiers written before element if (element is PsiNameIdentifierOwner) { @@ -426,6 +429,15 @@ object PositioningStrategies { } } + private class InlineFunPositioningStrategy : ModifierSetBasedPositioningStrategy(TokenSet.create(KtTokens.INLINE_KEYWORD)) { + override fun mark(element: KtModifierListOwner): List { + if (element is KtProperty) { + return markModifier(element.getter) ?: markModifier(element.setter) ?: super.mark(element) + } + return super.mark(element) + } + } + @JvmField val VISIBILITY_MODIFIER: PositioningStrategy = ModifierSetBasedPositioningStrategy(VISIBILITY_MODIFIERS) @@ -444,6 +456,9 @@ object PositioningStrategies { val INLINE_PARAMETER_MODIFIER: PositioningStrategy = ModifierSetBasedPositioningStrategy(TokenSet.create(KtTokens.NOINLINE_KEYWORD, KtTokens.CROSSINLINE_KEYWORD)) + @JvmField + val INLINE_FUN_MODIFIER: PositioningStrategy = InlineFunPositioningStrategy() + @JvmField val VARIANCE_IN_PROJECTION: PositioningStrategy = object : PositioningStrategy() { override fun mark(element: KtTypeProjection): List { diff --git a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/SourceElementPositioningStrategies.kt b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/SourceElementPositioningStrategies.kt index 85c60306e1c..5a53c8633c8 100644 --- a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/SourceElementPositioningStrategies.kt +++ b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/SourceElementPositioningStrategies.kt @@ -315,6 +315,11 @@ object SourceElementPositioningStrategies { PositioningStrategies.INLINE_PARAMETER_MODIFIER ) + val INLINE_FUN_MODIFIER = SourceElementPositioningStrategy( + LightTreePositioningStrategies.INLINE_FUN_MODIFIER, + PositioningStrategies.INLINE_FUN_MODIFIER + ) + val OPERATOR_MODIFIER = SourceElementPositioningStrategy( LightTreePositioningStrategies.OPERATOR_MODIFIER, PositioningStrategies.OPERATOR_MODIFIER diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 3ef3b7e78b5..62131795258 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -1163,7 +1163,7 @@ public interface Errors { DiagnosticFactory2 USAGE_IS_NOT_INLINABLE = DiagnosticFactory2.create(ERROR); DiagnosticFactory2 NULLABLE_INLINE_PARAMETER = DiagnosticFactory2.create(ERROR); DiagnosticFactory2 RECURSION_IN_INLINE = DiagnosticFactory2.create(ERROR); - DiagnosticFactory0 DECLARATION_CANT_BE_INLINED = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); + DiagnosticFactory0 DECLARATION_CANT_BE_INLINED = DiagnosticFactory0.create(ERROR, INLINE_FUN_MODIFIER); DiagnosticFactory0 OVERRIDE_BY_INLINE = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE); DiagnosticFactory0 REIFIED_TYPE_PARAMETER_IN_OVERRIDE = DiagnosticFactory0.create(ERROR); DiagnosticFactory1 INLINE_CALL_CYCLE = DiagnosticFactory1.create(ERROR, DEFAULT); diff --git a/compiler/testData/diagnostics/tests/inline/nonVirtualMembersWithInline.kt b/compiler/testData/diagnostics/tests/inline/nonVirtualMembersWithInline.kt index 7f469a01d7f..4c65f219724 100644 --- a/compiler/testData/diagnostics/tests/inline/nonVirtualMembersWithInline.kt +++ b/compiler/testData/diagnostics/tests/inline/nonVirtualMembersWithInline.kt @@ -14,17 +14,17 @@ abstract class A { inline final fun good4() {} - inline open protected fun wrong1() {} + inline open protected fun wrong1() {} - inline open public fun wrong2() {} + inline open public fun wrong2() {} - inline open fun wrong3() {} + inline open fun wrong3() {} - inline abstract protected fun wrong4() + inline abstract protected fun wrong4() - inline abstract public fun wrong5() + inline abstract public fun wrong5() - inline abstract fun wrong6() + inline abstract fun wrong6() } @@ -32,17 +32,17 @@ interface B { inline private fun good1() {} - inline fun wrong1() {} + inline fun wrong1() {} - inline open fun wrong2() {} + inline open fun wrong2() {} - inline open public fun wrong3() {} + inline open public fun wrong3() {} - inline open fun wrong4() {} + inline open fun wrong4() {} - inline fun wrong5() + inline fun wrong5() - inline public fun wrong6() + inline public fun wrong6() - inline fun wrong7() + inline fun wrong7() } diff --git a/compiler/testData/diagnostics/tests/inline/overrideWithInline.kt b/compiler/testData/diagnostics/tests/inline/overrideWithInline.kt index 99f0e329137..27452aaecca 100644 --- a/compiler/testData/diagnostics/tests/inline/overrideWithInline.kt +++ b/compiler/testData/diagnostics/tests/inline/overrideWithInline.kt @@ -35,12 +35,12 @@ class CDerived : IBase { open class COpen : IBase { override inline final fun foo() {} - override inline fun bar() {} + override inline fun bar() {} override inline final fun <reified T> qux(x: T) {} open class COpenNested : IBase { override inline final fun foo() {} - override inline fun bar() {} + override inline fun bar() {} override inline final fun <reified T> qux(x: T) {} } @@ -53,7 +53,7 @@ open class COpen : IBase { fun aMethod() { open class COpenLocal : IBase { override inline final fun foo() {} - override inline fun bar() {} + override inline fun bar() {} override inline final fun <reified T> qux(x: T) {} } } diff --git a/compiler/testData/diagnostics/tests/inline/property/virtualProperty.kt b/compiler/testData/diagnostics/tests/inline/property/virtualProperty.kt index 761e8bbbbe6..534e7ceb570 100644 --- a/compiler/testData/diagnostics/tests/inline/property/virtualProperty.kt +++ b/compiler/testData/diagnostics/tests/inline/property/virtualProperty.kt @@ -17,23 +17,23 @@ final class FinalProperty { open class OpenProperty { - inline open val valProp: Int + inline open val valProp: Int get() = 1 - open val valProp_1: Int - inline get() = 1 + open val valProp_1: Int + inline get() = 1 - inline open var varProp: Int + inline open var varProp: Int get() = 1 set(p: Int) {} - open var varProp_2: Int + open var varProp_2: Int get() = 1 - inline set(p: Int) {} + inline set(p: Int) {} } interface AbstractProperty { - inline abstract val valProp: Int - inline abstract var varProp: Int + inline abstract val valProp: Int + inline abstract var varProp: Int }