FE: report DECLARATION_CANT_BE_INLINED at 'inline' modifier

#KT-44022 Fixed
This commit is contained in:
Mikhail Glukhikh
2021-11-25 10:45:54 +03:00
parent 4df937ff7f
commit 2f1d415e4d
10 changed files with 111 additions and 42 deletions
@@ -1320,7 +1320,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
parameter<Symbol>("symbol")
}
val DECLARATION_CANT_BE_INLINED by error<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
val DECLARATION_CANT_BE_INLINED by error<KtDeclaration>(PositioningStrategy.INLINE_FUN_MODIFIER)
val OVERRIDE_BY_INLINE by warning<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
@@ -112,6 +112,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
IMPORT_ALIAS,
DECLARATION_START_TO_NAME,
REDUNDANT_NULLABLE,
INLINE_FUN_MODIFIER,
;
@@ -689,7 +689,7 @@ object FirErrors {
val PROTECTED_CALL_FROM_PUBLIC_INLINE by warning2<KtElement, FirBasedSymbol<*>, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val PRIVATE_CLASS_MEMBER_FROM_INLINE by error2<KtElement, FirBasedSymbol<*>, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val SUPER_CALL_FROM_PUBLIC_INLINE by error1<KtElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val DECLARATION_CANT_BE_INLINED by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
val DECLARATION_CANT_BE_INLINED by error0<KtDeclaration>(SourceElementPositioningStrategies.INLINE_FUN_MODIFIER)
val OVERRIDE_BY_INLINE by warning0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
val NON_INTERNAL_PUBLISHED_API by error0<KtElement>()
val INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE by error2<KtElement, FirExpression, FirValueParameterSymbol>()
@@ -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<LighterASTNode>,
baseNode: LighterASTNode
): List<TextRange>? {
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<LighterASTNode>
): List<TextRange> {
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<LighterASTNode>
): List<TextRange> {
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<LighterASTNode>.overrideModifier(declaration:
modifierList(declaration)?.let { findChildByType(it, KtTokens.OVERRIDE_KEYWORD) }
fun FlyweightCapableTreeStructure<LighterASTNode>.inlineModifier(declaration: LighterASTNode): LighterASTNode? =
modifierList(declaration)?.let { findChildByType(it, KtTokens.INLINE_KEYWORD) }
modifierList(declaration)?.let { findChildByType(it, INLINE_KEYWORD) }
fun FlyweightCapableTreeStructure<LighterASTNode>.typeParametersList(declaration: LighterASTNode): LighterASTNode? =
findChildByType(declaration, KtNodeTypes.TYPE_PARAMETER_LIST)
@@ -1241,6 +1273,22 @@ fun FlyweightCapableTreeStructure<LighterASTNode>.userType(node: LighterASTNode)
private fun FlyweightCapableTreeStructure<LighterASTNode>.supertypesList(node: LighterASTNode): LighterASTNode? =
findChildByType(node, KtNodeTypes.SUPER_TYPE_LIST)
private fun FlyweightCapableTreeStructure<LighterASTNode>.getter(node: LighterASTNode): LighterASTNode? {
val childrenRef = Ref<Array<LighterASTNode?>>()
getChildren(node, childrenRef)
return childrenRef.get()?.firstOrNull {
it != null && it.tokenType == KtNodeTypes.PROPERTY_ACCESSOR && findChildByType(it, GET_KEYWORD) != null
}
}
private fun FlyweightCapableTreeStructure<LighterASTNode>.setter(node: LighterASTNode): LighterASTNode? {
val childrenRef = Ref<Array<LighterASTNode?>>()
getChildren(node, childrenRef)
return childrenRef.get()?.firstOrNull {
it != null && it.tokenType == KtNodeTypes.PROPERTY_ACCESSOR && findChildByType(it, SET_KEYWORD) != null
}
}
private fun FlyweightCapableTreeStructure<LighterASTNode>.accessorNamePlaceholder(node: LighterASTNode): LighterASTNode =
findChildByType(node, KtTokens.GET_KEYWORD) ?: findChildByType(node, KtTokens.SET_KEYWORD)!!
@@ -399,12 +399,15 @@ object PositioningStrategies {
}
}
private class ModifierSetBasedPositioningStrategy(private val modifierSet: TokenSet) : PositioningStrategy<KtModifierListOwner>() {
override fun mark(element: KtModifierListOwner): List<TextRange> {
val modifierList = element.modifierList
private open class ModifierSetBasedPositioningStrategy(private val modifierSet: TokenSet) : PositioningStrategy<KtModifierListOwner>() {
protected fun markModifier(element: KtModifierListOwner?): List<TextRange>? =
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<TextRange> {
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<TextRange> {
if (element is KtProperty) {
return markModifier(element.getter) ?: markModifier(element.setter) ?: super.mark(element)
}
return super.mark(element)
}
}
@JvmField
val VISIBILITY_MODIFIER: PositioningStrategy<KtModifierListOwner> = ModifierSetBasedPositioningStrategy(VISIBILITY_MODIFIERS)
@@ -444,6 +456,9 @@ object PositioningStrategies {
val INLINE_PARAMETER_MODIFIER: PositioningStrategy<KtModifierListOwner> =
ModifierSetBasedPositioningStrategy(TokenSet.create(KtTokens.NOINLINE_KEYWORD, KtTokens.CROSSINLINE_KEYWORD))
@JvmField
val INLINE_FUN_MODIFIER: PositioningStrategy<KtModifierListOwner> = InlineFunPositioningStrategy()
@JvmField
val VARIANCE_IN_PROJECTION: PositioningStrategy<KtTypeProjection> = object : PositioningStrategy<KtTypeProjection>() {
override fun mark(element: KtTypeProjection): List<TextRange> {
@@ -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
@@ -1163,7 +1163,7 @@ public interface Errors {
DiagnosticFactory2<KtElement, KtExpression, DeclarationDescriptor> USAGE_IS_NOT_INLINABLE = DiagnosticFactory2.create(ERROR);
DiagnosticFactory2<KtElement, KtElement, DeclarationDescriptor> NULLABLE_INLINE_PARAMETER = DiagnosticFactory2.create(ERROR);
DiagnosticFactory2<KtElement, KtElement, DeclarationDescriptor> RECURSION_IN_INLINE = DiagnosticFactory2.create(ERROR);
DiagnosticFactory0<KtDeclaration> DECLARATION_CANT_BE_INLINED = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
DiagnosticFactory0<KtDeclaration> DECLARATION_CANT_BE_INLINED = DiagnosticFactory0.create(ERROR, INLINE_FUN_MODIFIER);
DiagnosticFactory0<KtDeclaration> OVERRIDE_BY_INLINE = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE);
DiagnosticFactory0<PsiElement> REIFIED_TYPE_PARAMETER_IN_OVERRIDE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<PsiElement, CallableDescriptor> INLINE_CALL_CYCLE = DiagnosticFactory1.create(ERROR, DEFAULT);
@@ -14,17 +14,17 @@ abstract class A {
inline final fun good4() {}
<!DECLARATION_CANT_BE_INLINED!>inline open protected fun wrong1()<!> {}
<!DECLARATION_CANT_BE_INLINED!>inline<!> open protected fun wrong1() {}
<!DECLARATION_CANT_BE_INLINED!>inline open public fun wrong2()<!> {}
<!DECLARATION_CANT_BE_INLINED!>inline<!> open public fun wrong2() {}
<!DECLARATION_CANT_BE_INLINED!>inline open fun wrong3()<!> {}
<!DECLARATION_CANT_BE_INLINED!>inline<!> open fun wrong3() {}
<!DECLARATION_CANT_BE_INLINED!>inline abstract protected fun wrong4()<!>
<!DECLARATION_CANT_BE_INLINED!>inline<!> abstract protected fun wrong4()
<!DECLARATION_CANT_BE_INLINED!>inline abstract public fun wrong5()<!>
<!DECLARATION_CANT_BE_INLINED!>inline<!> abstract public fun wrong5()
<!DECLARATION_CANT_BE_INLINED!>inline abstract fun wrong6()<!>
<!DECLARATION_CANT_BE_INLINED!>inline<!> abstract fun wrong6()
}
@@ -32,17 +32,17 @@ interface B {
inline private fun good1() {}
<!DECLARATION_CANT_BE_INLINED!>inline fun wrong1()<!> {}
<!DECLARATION_CANT_BE_INLINED!>inline<!> fun wrong1() {}
<!DECLARATION_CANT_BE_INLINED!>inline open fun wrong2()<!> {}
<!DECLARATION_CANT_BE_INLINED!>inline<!> open fun wrong2() {}
<!DECLARATION_CANT_BE_INLINED!>inline open public fun wrong3()<!> {}
<!DECLARATION_CANT_BE_INLINED!>inline<!> open public fun wrong3() {}
<!DECLARATION_CANT_BE_INLINED!>inline open fun wrong4()<!> {}
<!DECLARATION_CANT_BE_INLINED!>inline<!> open fun wrong4() {}
<!DECLARATION_CANT_BE_INLINED!>inline fun wrong5()<!>
<!DECLARATION_CANT_BE_INLINED!>inline<!> fun wrong5()
<!DECLARATION_CANT_BE_INLINED!>inline public fun wrong6()<!>
<!DECLARATION_CANT_BE_INLINED!>inline<!> public fun wrong6()
<!DECLARATION_CANT_BE_INLINED!>inline fun wrong7()<!>
<!DECLARATION_CANT_BE_INLINED!>inline<!> fun wrong7()
}
@@ -35,12 +35,12 @@ class CDerived : IBase {
open class COpen : IBase {
<!OVERRIDE_BY_INLINE!>override inline final fun foo()<!> {}
<!DECLARATION_CANT_BE_INLINED!>override inline fun bar()<!> {}
override <!DECLARATION_CANT_BE_INLINED!>inline<!> fun bar() {}
<!OVERRIDE_BY_INLINE!>override inline final fun <<!REIFIED_TYPE_PARAMETER_IN_OVERRIDE!>reified<!> T> qux(x: T)<!> {}
open class COpenNested : IBase {
<!OVERRIDE_BY_INLINE!>override inline final fun foo()<!> {}
<!DECLARATION_CANT_BE_INLINED!>override inline fun bar()<!> {}
override <!DECLARATION_CANT_BE_INLINED!>inline<!> fun bar() {}
<!OVERRIDE_BY_INLINE!>override inline final fun <<!REIFIED_TYPE_PARAMETER_IN_OVERRIDE!>reified<!> T> qux(x: T)<!> {}
}
@@ -53,7 +53,7 @@ open class COpen : IBase {
fun aMethod() {
open class COpenLocal : IBase {
<!OVERRIDE_BY_INLINE!>override inline final fun foo()<!> {}
<!DECLARATION_CANT_BE_INLINED!>override inline fun bar()<!> {}
override <!DECLARATION_CANT_BE_INLINED!>inline<!> fun bar() {}
<!OVERRIDE_BY_INLINE!>override inline final fun <<!REIFIED_TYPE_PARAMETER_IN_OVERRIDE!>reified<!> T> qux(x: T)<!> {}
}
}
@@ -17,23 +17,23 @@ final class FinalProperty {
open class OpenProperty {
<!DECLARATION_CANT_BE_INLINED!>inline open val valProp: Int<!>
<!DECLARATION_CANT_BE_INLINED!>inline<!> open val valProp: Int
get() = 1
<!DECLARATION_CANT_BE_INLINED!>open val valProp_1: Int<!>
inline get() = 1
open val valProp_1: Int
<!DECLARATION_CANT_BE_INLINED!>inline<!> get() = 1
<!DECLARATION_CANT_BE_INLINED!>inline open var varProp: Int<!>
<!DECLARATION_CANT_BE_INLINED!>inline<!> open var varProp: Int
get() = 1
set(p: Int) {}
<!DECLARATION_CANT_BE_INLINED!>open var varProp_2: Int<!>
open var varProp_2: Int
get() = 1
inline set(p: Int) {}
<!DECLARATION_CANT_BE_INLINED!>inline<!> set(p: Int) {}
}
interface AbstractProperty {
<!DECLARATION_CANT_BE_INLINED!>inline abstract val valProp: Int<!>
<!DECLARATION_CANT_BE_INLINED!>inline abstract var varProp: Int<!>
<!DECLARATION_CANT_BE_INLINED!>inline<!> abstract val valProp: Int
<!DECLARATION_CANT_BE_INLINED!>inline<!> abstract var varProp: Int
}