diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/declarationCheckers.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/declarationCheckers.kt index d9744c56b74..cfe714713c4 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/declarationCheckers.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/declarationCheckers.kt @@ -45,7 +45,7 @@ class LocalFunInlineChecker : SimpleDeclarationChecker { declaration is KtNamedFunction && descriptor is FunctionDescriptor && descriptor.visibility == Visibilities.LOCAL) { - diagnosticHolder.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(declaration, declaration, descriptor)) + diagnosticHolder.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(declaration, "Local inline functions")) } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index a95847df0bd..cf94aefae56 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -937,7 +937,7 @@ public interface Errors { DiagnosticFactory2 NON_PUBLIC_CALL_FROM_PUBLIC_INLINE = DiagnosticFactory2.create(ERROR, CALL_ELEMENT); DiagnosticFactory2 PRIVATE_CLASS_MEMBER_FROM_INLINE = DiagnosticFactory2.create(ERROR, CALL_ELEMENT); DiagnosticFactory1 NON_LOCAL_RETURN_NOT_ALLOWED = DiagnosticFactory1.create(ERROR, CALL_ELEMENT); - DiagnosticFactory2 NOT_YET_SUPPORTED_IN_INLINE = DiagnosticFactory2.create(ERROR); + DiagnosticFactory1 NOT_YET_SUPPORTED_IN_INLINE = DiagnosticFactory1.create(ERROR, NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT); DiagnosticFactory1 NOTHING_TO_INLINE = DiagnosticFactory1.create(WARNING); DiagnosticFactory2 USAGE_IS_NOT_INLINABLE = DiagnosticFactory2.create(ERROR); DiagnosticFactory2 NULLABLE_INLINE_PARAMETER = DiagnosticFactory2.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index cb9dc99cf46..65e664099be 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -184,6 +184,25 @@ object PositioningStrategies { } } + @JvmField val NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: KtDeclaration): List = + markElement( + when (element) { + is KtClassOrObject -> + element.getDeclarationKeyword() ?: + element.nameIdentifier ?: + element + + is KtNamedFunction -> + element.modifierList?.getModifier(KtTokens.INLINE_KEYWORD) ?: + element.funKeyword ?: + element + + else -> element + } + ) + } + @JvmField val TYPE_PARAMETERS_OR_DECLARATION_SIGNATURE: PositioningStrategy = object : PositioningStrategy() { override fun mark(element: KtDeclaration): List { if (element is KtTypeParameterListOwner) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 7bd6b5df150..a0ee7da7873 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -851,7 +851,7 @@ public class DefaultErrorMessages { //Inline MAP.put(NON_PUBLIC_CALL_FROM_PUBLIC_INLINE, "Public-API inline function cannot access non-public-API ''{0}''", SHORT_NAMES_IN_TYPES, SHORT_NAMES_IN_TYPES); MAP.put(PRIVATE_CLASS_MEMBER_FROM_INLINE, "Non-private inline function cannot access members of private classes: ''{0}''", SHORT_NAMES_IN_TYPES, SHORT_NAMES_IN_TYPES); - MAP.put(NOT_YET_SUPPORTED_IN_INLINE, "''{0}'' construction is not yet supported in inline functions", ELEMENT_TEXT, SHORT_NAMES_IN_TYPES); + MAP.put(NOT_YET_SUPPORTED_IN_INLINE, "{0} are not yet supported in inline functions", STRING); MAP.put(DECLARATION_CANT_BE_INLINED, "'inline' modifier is not allowed on virtual members. Only private or final members can be inlined"); MAP.put(OVERRIDE_BY_INLINE, "Override by an inline function"); MAP.put(REIFIED_TYPE_PARAMETER_IN_OVERRIDE, "Override by a function with reified type parameter"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtClassOrObject.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtClassOrObject.kt index 5a44bb3ad00..4474e7350db 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtClassOrObject.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtClassOrObject.kt @@ -23,6 +23,7 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.impl.CheckUtil import com.intellij.psi.stubs.IStubElementType +import com.intellij.psi.tree.TokenSet import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub @@ -110,6 +111,11 @@ abstract class KtClassOrObject : fun isAnnotation(): Boolean = hasModifier(KtTokens.ANNOTATION_KEYWORD) + fun getDeclarationKeyword(): PsiElement? = + findChildByType(TokenSet.create( + KtTokens.CLASS_KEYWORD, KtTokens.INTERFACE_KEYWORD, KtTokens.OBJECT_KEYWORD + )) + override fun delete() { CheckUtil.checkWritable(this) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt index b19253d92bb..fdf6348fd07 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt @@ -67,7 +67,7 @@ class InlineAnalyzerExtension( } override fun visitClass(klass: KtClass) { - trace.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(klass, klass, descriptor)) + trace.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(klass, "Local classes")) } override fun visitNamedFunction(function: KtNamedFunction) { @@ -75,7 +75,7 @@ class InlineAnalyzerExtension( super.visitNamedFunction(function) } else { - trace.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(function, function, descriptor)) + trace.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(function, "Local functions")) } } } @@ -95,7 +95,7 @@ class InlineAnalyzerExtension( val inheritDefaultValues = !parameter.declaresDefaultValue() if (checkInlinableParameter(parameter, ktParameter, functionDescriptor, null) || inheritDefaultValues) { if (inheritDefaultValues || !languageVersionSettings.supportsFeature(LanguageFeature.InlineDefaultFunctionalParameters)) { - trace.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(ktParameter, ktParameter, functionDescriptor)) + trace.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(ktParameter, "Functional parameters with inherited default values")) } else { checkDefaultValue(trace, parameter, ktParameter) diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt10823.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt10823.kt index 219b9c33f24..0c003eb202f 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt10823.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt10823.kt @@ -17,9 +17,9 @@ fun find(): Any? { } fun find4(): Any? { - inline fun visit(element: Any) { + inline fun visit(element: Any) { return@find4 element - } + } return null } diff --git a/compiler/testData/diagnostics/tests/inline/localFun.kt b/compiler/testData/diagnostics/tests/inline/localFun.kt index 9b121f25570..7746fb034ab 100644 --- a/compiler/testData/diagnostics/tests/inline/localFun.kt +++ b/compiler/testData/diagnostics/tests/inline/localFun.kt @@ -1,4 +1,4 @@ fun main(args: Array) { - inline fun a(){ - } + inline fun a(){ + } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inline/messagesForUnsupportedInInline.kt b/compiler/testData/diagnostics/tests/inline/messagesForUnsupportedInInline.kt new file mode 100644 index 00000000000..3f4e718028e --- /dev/null +++ b/compiler/testData/diagnostics/tests/inline/messagesForUnsupportedInInline.kt @@ -0,0 +1,18 @@ +inline fun inlineFun() { + fun localFun() {} + class LocalClass {} +} + +fun outerFun() { + inline fun localInlineFun() {} +} + +abstract class Base { + abstract fun withDefault(f: () -> Unit = { -> }) +} + +class Derived : Base() { + override final inline fun withDefault( + f: () -> Unit + ) {} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inline/messagesForUnsupportedInInline.txt b/compiler/testData/diagnostics/tests/inline/messagesForUnsupportedInInline.txt new file mode 100644 index 00000000000..b4b0f8fae87 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inline/messagesForUnsupportedInInline.txt @@ -0,0 +1,20 @@ +package + +public inline fun inlineFun(): kotlin.Unit +public fun outerFun(): kotlin.Unit + +public abstract class Base { + public constructor Base() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + public abstract fun withDefault(/*0*/ f: () -> kotlin.Unit = ...): kotlin.Unit +} + +public final class Derived : Base { + public constructor Derived() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + public final inline override /*1*/ fun withDefault(/*0*/ f: () -> kotlin.Unit = ...): kotlin.Unit +} diff --git a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/localFun.kt b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/localFun.kt index 6a5e5ecaa4f..412a635203c 100644 --- a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/localFun.kt +++ b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/localFun.kt @@ -1,15 +1,15 @@ // !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE inline fun inlineFunOnlyLocal(crossinline p: () -> R) { - fun a() { + fun a() { val z = p() - } + } a() } inline fun inlineFun(p: () -> R) { - fun a() { + fun a() { p() - } + } a() } diff --git a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/nonInlinedClass.kt b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/nonInlinedClass.kt index 1ce9497c5f1..065f8daf4bf 100644 --- a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/nonInlinedClass.kt +++ b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/nonInlinedClass.kt @@ -1,23 +1,23 @@ // !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE inline fun inlineFunOnlyLocal(crossinline p: () -> R) { - class A { + class A { val z = p() fun a() { p() } - } + } } inline fun inlineFun(p: () -> R) { - class A { + class A { val z = p() fun a() { p() } - } + } } diff --git a/compiler/testData/diagnostics/tests/inline/nonPublicMember/localClass2.kt b/compiler/testData/diagnostics/tests/inline/nonPublicMember/localClass2.kt index c77f9cbccee..182426e82ac 100644 --- a/compiler/testData/diagnostics/tests/inline/nonPublicMember/localClass2.kt +++ b/compiler/testData/diagnostics/tests/inline/nonPublicMember/localClass2.kt @@ -6,8 +6,8 @@ public fun test() { } } - inline fun localFun2() { + inline fun localFun2() { Z().localFun() - } + } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inline/nonPublicMember/localFun.kt b/compiler/testData/diagnostics/tests/inline/nonPublicMember/localFun.kt index ccb0c0e7e93..25e80fb1e92 100644 --- a/compiler/testData/diagnostics/tests/inline/nonPublicMember/localFun.kt +++ b/compiler/testData/diagnostics/tests/inline/nonPublicMember/localFun.kt @@ -4,8 +4,8 @@ public fun test() { } - inline fun localFun2() { + inline fun localFun2() { localFun() - } + } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inline/property/unsupportedConstruction.kt b/compiler/testData/diagnostics/tests/inline/property/unsupportedConstruction.kt index 4c0037fd291..31e0d73998b 100644 --- a/compiler/testData/diagnostics/tests/inline/property/unsupportedConstruction.kt +++ b/compiler/testData/diagnostics/tests/inline/property/unsupportedConstruction.kt @@ -3,18 +3,18 @@ inline val z: Int get() { - class A { + class A { fun a() { class AInner {} } - } + } object B{ object BInner {} } - fun local() { + fun local() { fun localInner() {} - } + } return 1 } diff --git a/compiler/testData/diagnostics/tests/inline/unsupportedConstruction.kt b/compiler/testData/diagnostics/tests/inline/unsupportedConstruction.kt index 0e9014ba2d9..4b74c687b86 100644 --- a/compiler/testData/diagnostics/tests/inline/unsupportedConstruction.kt +++ b/compiler/testData/diagnostics/tests/inline/unsupportedConstruction.kt @@ -3,19 +3,19 @@ inline fun unsupported() { - class A { + class A { fun a() { class AInner {} } - } + } object B{ object BInner {} } - fun local() { + fun local() { fun localInner() {} - } + } } inline fun unsupportedDefault(s : ()->Unit = {}) { diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index e501f29f573..9c8f883c9d2 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -11353,6 +11353,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("messagesForUnsupportedInInline.kt") + public void testMessagesForUnsupportedInInline() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inline/messagesForUnsupportedInInline.kt"); + doTest(fileName); + } + @TestMetadata("nonVirtualMembersWithInline.kt") public void testNonVirtualMembersWithInline() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inline/nonVirtualMembersWithInline.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 2d9f3e86c19..90893a7d078 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -11353,6 +11353,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing doTest(fileName); } + @TestMetadata("messagesForUnsupportedInInline.kt") + public void testMessagesForUnsupportedInInline() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inline/messagesForUnsupportedInInline.kt"); + doTest(fileName); + } + @TestMetadata("nonVirtualMembersWithInline.kt") public void testNonVirtualMembersWithInline() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inline/nonVirtualMembersWithInline.kt");