diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/inlineOnly.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/inlineOnly.kt index 51a7336e488..dbb162536eb 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/inlineOnly.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/inlineOnly.kt @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.DescriptorUtils -private val INLINE_ONLY_ANNOTATION_FQ_NAME = FqName("kotlin.internal.InlineOnly") +val INLINE_ONLY_ANNOTATION_FQ_NAME = FqName("kotlin.internal.InlineOnly") /** * @return true if it's impossible to observe a call instruction referencing this member in the bytecode. diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt index 8644d61ba4a..3c82ffc4fcd 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker +import org.jetbrains.kotlin.resolve.inline.INLINE_ONLY_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature @@ -315,8 +316,6 @@ private tailrec fun isInlineOrContainedInInline(declaration: IrDeclaration?): Bo /* Borrowed from inlineOnly.kt */ -private val INLINE_ONLY_ANNOTATION_FQ_NAME = FqName("kotlin.internal.InlineOnly") - fun IrDeclarationWithVisibility.isInlineOnlyOrReifiable(): Boolean = this is IrFunction && (isReifiable() || isInlineOnly()) diff --git a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/breakpoints/KotlinFunctionBreakpointType.java b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/breakpoints/KotlinFunctionBreakpointType.java index 11431e456cc..bc11c59caba 100644 --- a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/breakpoints/KotlinFunctionBreakpointType.java +++ b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/breakpoints/KotlinFunctionBreakpointType.java @@ -153,7 +153,11 @@ public class KotlinFunctionBreakpointType if (element instanceof KtFunction) { KtFunction function = (KtFunction) element; - return ApplicabilityResult.maybe(function.hasBody() && !KtPsiUtil.isLocal(function)); + return ApplicabilityResult.maybe( + function.hasBody() + && !KtPsiUtil.isLocal(function) + && !BreakpointTypeUtilsKt.isInlineOnly(function) + ); } if (element instanceof KtPropertyAccessor) { diff --git a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/breakpoints/KotlinLineBreakpointType.java b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/breakpoints/KotlinLineBreakpointType.java index 2e4d26c33cb..8152a802418 100644 --- a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/breakpoints/KotlinLineBreakpointType.java +++ b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/breakpoints/KotlinLineBreakpointType.java @@ -135,6 +135,14 @@ public class KotlinLineBreakpointType extends JavaLineBreakpointType implements return ApplicabilityResult.MAYBE_YES; } + PsiElement containingMethod = getContainingMethod(element); + if (containingMethod instanceof KtCallableDeclaration) { + KtCallableDeclaration callable = (KtCallableDeclaration) containingMethod; + if (BreakpointTypeUtilsKt.isInlineOnly(callable)) { + return ApplicabilityResult.DEFINITELY_NO; + } + } + if (isClosingBraceInMethod(element)) { return ApplicabilityResult.MAYBE_YES; } diff --git a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/breakpoints/breakpointTypeUtils.kt b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/breakpoints/breakpointTypeUtils.kt index a1c22ca255f..dfdd64c1168 100644 --- a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/breakpoints/breakpointTypeUtils.kt +++ b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/breakpoints/breakpointTypeUtils.kt @@ -31,11 +31,17 @@ import com.intellij.xdebugger.XDebuggerUtil import com.intellij.xdebugger.XSourcePosition import com.intellij.xdebugger.impl.XSourcePositionImpl import org.jetbrains.kotlin.idea.KotlinFileType +import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.core.util.CodeInsightUtils import org.jetbrains.kotlin.idea.core.util.getLineNumber import org.jetbrains.kotlin.idea.debugger.findElementAtLine +import org.jetbrains.kotlin.idea.util.application.runReadAction +import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.inline.INLINE_ONLY_ANNOTATION_FQ_NAME +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance import java.util.* @@ -55,6 +61,9 @@ class ApplicabilityResult(val isApplicable: Boolean, val shouldStop: Boolean) { @JvmField val DEFINITELY_YES = ApplicabilityResult(isApplicable = true, shouldStop = true) + @JvmField + val DEFINITELY_NO = ApplicabilityResult(isApplicable = false, shouldStop = true) + @JvmField val MAYBE_YES = ApplicabilityResult(isApplicable = true, shouldStop = false) } @@ -181,3 +190,18 @@ fun getLambdasAtLineIfAny(file: KtFile, line: Int): List { } } +internal fun KtCallableDeclaration.isInlineOnly(): Boolean { + if (!hasModifier(KtTokens.INLINE_KEYWORD)) { + return false + } + + val inlineOnlyAnnotation = annotationEntries + .firstOrNull { it.shortName == INLINE_ONLY_ANNOTATION_FQ_NAME.shortName() } + ?: return false + + return runReadAction f@{ + val bindingContext = inlineOnlyAnnotation.analyze(BodyResolveMode.PARTIAL) + val annotationDescriptor = bindingContext[BindingContext.ANNOTATION, inlineOnlyAnnotation] ?: return@f false + return@f annotationDescriptor.fqName == INLINE_ONLY_ANNOTATION_FQ_NAME + } +} \ No newline at end of file diff --git a/idea/testData/debugger/breakpointApplicability/inlineOnly.kt b/idea/testData/debugger/breakpointApplicability/inlineOnly.kt new file mode 100644 index 00000000000..706c32abd99 --- /dev/null +++ b/idea/testData/debugger/breakpointApplicability/inlineOnly.kt @@ -0,0 +1,53 @@ +fun foo() { + require(true) { "foo" } /// *, L, λ + + require(true) { val a = 5 } /// *, L, λ + + require(true) { /// L + val a = 5 /// L + } /// L + + block { val a = 5 } /// *, L, λ + + block { /// L + val a = 5 /// L + } /// L + + inlineBlock { val a = 5} /// *, L, λ + + inlineBlock { /// L + val a = 5 /// L + } /// L + + inlineOnlyBlock { val a = 5 } /// *, L, λ + + inlineOnlyBlock { /// L + val a = 5 /// L + } /// L + + inlineOnlyBlock2 { val a = 5 } /// *, L, λ + + inlineOnlyBlock2 { /// L + val a = 5 /// L + } /// L +} /// L + +private fun block(block: () -> Unit) { /// M + block() /// L +} /// L + +private inline fun inlineBlock(block: () -> Unit) { /// M + block() /// L +} /// L + +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +@kotlin.internal.InlineOnly +private inline fun inlineOnlyBlock(block: () -> Unit) { + block() +} + +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +@kotlin.internal.InlineOnly +private inline fun inlineOnlyBlock2(noinline block: () -> Unit) { + block() +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/BreakpointApplicabilityTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/BreakpointApplicabilityTestGenerated.java index 1ba3d445ff6..acdebad5022 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/BreakpointApplicabilityTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/BreakpointApplicabilityTestGenerated.java @@ -39,6 +39,11 @@ public class BreakpointApplicabilityTestGenerated extends AbstractBreakpointAppl runTest("idea/testData/debugger/breakpointApplicability/functions.kt"); } + @TestMetadata("inlineOnly.kt") + public void testInlineOnly() throws Exception { + runTest("idea/testData/debugger/breakpointApplicability/inlineOnly.kt"); + } + @TestMetadata("locals.kt") public void testLocals() throws Exception { runTest("idea/testData/debugger/breakpointApplicability/locals.kt");