[FIR LT] Get correct startOffset value for declarations with comments

#KT-56913 Fixed
#KT-56926 Fixed
This commit is contained in:
Ivan Kylchik
2023-03-20 19:47:20 +01:00
committed by Space Team
parent e4591d7af9
commit 2b387e7a10
14 changed files with 414 additions and 6 deletions
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiCompiledElement
import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.builtins.StandardNames.DATA_CLASS_COMPONENT_PREFIX
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.startOffsetSkippingComments
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.builder.buildFileAnnotationsContainer
import org.jetbrains.kotlin.fir.builder.buildPackageDirective
@@ -61,6 +62,14 @@ import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.runIf
private fun AbstractKtSourceElement?.startOffsetSkippingComments(): Int? {
return when (this) {
is KtPsiSourceElement -> this.psi.startOffsetSkippingComments
is KtLightSourceElement -> this.startOffsetSkippingComments
else -> null
}
}
internal fun <T : IrElement> FirElement.convertWithOffsets(
f: (startOffset: Int, endOffset: Int) -> T
): T {
@@ -70,9 +79,8 @@ internal fun <T : IrElement> FirElement.convertWithOffsets(
internal fun <T : IrElement> KtSourceElement?.convertWithOffsets(
f: (startOffset: Int, endOffset: Int) -> T
): T {
val psi = psi
if (psi is PsiCompiledElement) return f(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
val startOffset = psi?.startOffsetSkippingComments ?: this?.startOffset ?: UNDEFINED_OFFSET
val startOffset = this?.startOffsetSkippingComments() ?: this?.startOffset ?: UNDEFINED_OFFSET
val endOffset = this?.endOffset ?: UNDEFINED_OFFSET
return f(startOffset, endOffset)
}
@@ -87,9 +95,8 @@ internal fun <T : IrElement> FirStatement.convertWithOffsets(
calleeReference: FirReference,
f: (startOffset: Int, endOffset: Int) -> T
): T {
val psi = calleeReference.psi
if (psi is PsiCompiledElement) return f(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
val startOffset = psi?.startOffsetSkippingComments ?: calleeReference.source?.startOffset ?: UNDEFINED_OFFSET
val startOffset = calleeReference.source?.startOffsetSkippingComments() ?: calleeReference.source?.startOffset ?: UNDEFINED_OFFSET
val endOffset = source?.endOffset ?: UNDEFINED_OFFSET
return f(startOffset, endOffset)
}
@@ -85,6 +85,30 @@ public class FirLightTreeSteppingTestGenerated extends AbstractFirLightTreeStepp
runTest("compiler/testData/debug/stepping/classObject.kt");
}
@Test
@TestMetadata("commentBeforeClass.kt")
public void testCommentBeforeClass() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeClass.kt");
}
@Test
@TestMetadata("commentBeforeCompanionProperty.kt")
public void testCommentBeforeCompanionProperty() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeCompanionProperty.kt");
}
@Test
@TestMetadata("commentBeforeFunctionWithDefault.kt")
public void testCommentBeforeFunctionWithDefault() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeFunctionWithDefault.kt");
}
@Test
@TestMetadata("comments.kt")
public void testComments() throws Exception {
runTest("compiler/testData/debug/stepping/comments.kt");
}
@Test
@TestMetadata("compileTimeConstant.kt")
public void testCompileTimeConstant() throws Exception {
@@ -367,6 +391,12 @@ public class FirLightTreeSteppingTestGenerated extends AbstractFirLightTreeStepp
runTest("compiler/testData/debug/stepping/nullcheck.kt");
}
@Test
@TestMetadata("overridenGetterSetter.kt")
public void testOverridenGetterSetter() throws Exception {
runTest("compiler/testData/debug/stepping/overridenGetterSetter.kt");
}
@Test
@TestMetadata("primitiveNullChecks.kt")
public void testPrimitiveNullChecks() throws Exception {
@@ -85,6 +85,30 @@ public class FirPsiSteppingTestGenerated extends AbstractFirPsiSteppingTest {
runTest("compiler/testData/debug/stepping/classObject.kt");
}
@Test
@TestMetadata("commentBeforeClass.kt")
public void testCommentBeforeClass() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeClass.kt");
}
@Test
@TestMetadata("commentBeforeCompanionProperty.kt")
public void testCommentBeforeCompanionProperty() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeCompanionProperty.kt");
}
@Test
@TestMetadata("commentBeforeFunctionWithDefault.kt")
public void testCommentBeforeFunctionWithDefault() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeFunctionWithDefault.kt");
}
@Test
@TestMetadata("comments.kt")
public void testComments() throws Exception {
runTest("compiler/testData/debug/stepping/comments.kt");
}
@Test
@TestMetadata("compileTimeConstant.kt")
public void testCompileTimeConstant() throws Exception {
@@ -367,6 +391,12 @@ public class FirPsiSteppingTestGenerated extends AbstractFirPsiSteppingTest {
runTest("compiler/testData/debug/stepping/nullcheck.kt");
}
@Test
@TestMetadata("overridenGetterSetter.kt")
public void testOverridenGetterSetter() throws Exception {
runTest("compiler/testData/debug/stepping/overridenGetterSetter.kt");
}
@Test
@TestMetadata("primitiveNullChecks.kt")
public void testPrimitiveNullChecks() throws Exception {
@@ -10,6 +10,7 @@ import com.intellij.openapi.util.Ref
import com.intellij.openapi.util.TextRange
import com.intellij.psi.TokenType
import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtLightSourceElement
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.lexer.KtTokens
@@ -101,3 +102,16 @@ private fun hasSyntaxErrors(node: LighterASTNode, tree: FlyweightCapableTreeStru
}?.let { hasSyntaxErrors(it, tree) } == true
}
val KtLightSourceElement.startOffsetSkippingComments: Int
get() {
val kidsRef = Ref<Array<LighterASTNode?>>()
treeStructure.getChildren(this.lighterASTNode, kidsRef)
val children = kidsRef.get()
// The solution to find first non comment children will not work here. `treeStructure` can have different root
// than original program. Because of that `startOffset` is relative and not in absolute value.
val comments = children.filterNotNull()
.takeWhile { it.tokenType in DOC_AND_COMMENT_TOKENS }
return startOffset + comments.sumOf { it.textLength }
}
+21
View File
@@ -0,0 +1,21 @@
// FILE: test.kt
fun box() {
A()
}
// Some comment
class A {
}
// EXPECTATIONS JVM JVM_IR
// test.kt:4 box
// test.kt:8 <init>
// test.kt:4 box
// test.kt:5 box
// EXPECTATIONS JS_IR
// test.kt:4 box
// test.kt:8 <init>
// test.kt:5 box
@@ -0,0 +1,26 @@
// FILE: test.kt
class AWithCompanion {
companion object {
//Comment before
val compPropVal = 1
}
}
fun box() {
AWithCompanion.compPropVal
}
// EXPECTATIONS JVM JVM_IR
// test.kt:11 box
// test.kt:6 <clinit>
// test.kt:6 getCompPropVal
// test.kt:6 getCompPropVal
// test.kt:11 box
// test.kt:12 box
// EXPECTATIONS JS_IR
// test.kt:11 box
// test.kt:6 <init>
// test.kt:4 <init>
// test.kt:12 box
@@ -0,0 +1,20 @@
// FILE: test.kt
// Comment before
fun foo(i: Int = 1): Int {
return i
}
fun box() {
foo()
}
// EXPECTATIONS JVM JVM_IR
// test.kt:9 box
// test.kt:5 foo
// test.kt:9 box
// test.kt:10 box
// EXPECTATIONS JS_IR
// test.kt:9 box
// test.kt:10 box
+54
View File
@@ -0,0 +1,54 @@
// FILE: test.kt
// Single line comment
fun box() {
A().foo()
A().bar()
}
/*
Multi
line
comment
*/
class A {
/**
* Doc
* comment
*/
fun foo() {
}
// Single line comment 1
// Single line comment 2
fun bar() {
}
}
// EXPECTATIONS JVM JVM_IR
// test.kt:5 box
// test.kt:15 <init>
// test.kt:5 box
// test.kt:24 foo
// test.kt:6 box
// test.kt:15 <init>
// test.kt:6 box
// test.kt:31 bar
// test.kt:7 box
// EXPECTATIONS JS_IR
// test.kt:5 box
// test.kt:15 <init>
// test.kt:5 box
// test.kt:24 foo
// test.kt:6 box
// test.kt:15 <init>
// test.kt:6 box
// test.kt:31 bar
// test.kt:7 box
@@ -0,0 +1,86 @@
// FILE: test.kt
interface MyInterfaceWithoutBreakpoints {
val propVal2: Int
var propVar2: Int
fun testPropertyInInterface() {
propVal2
propVar2
propVar2 = 2
}
}
// Breakpoint at GETFILED/PUTFIELD
class MyInterfaceImplWithBreakpoints : MyInterfaceWithoutBreakpoints {
//FieldWatchpoint! (propVal2)
override val propVal2 = 1
//FieldWatchpoint! (propVar2)
override var propVar2 = 1
fun testPropertyInInterfaceImpl() {
propVal2
propVar2
propVar2 = 2
}
}
fun box() {
val macwbi = MyInterfaceImplWithBreakpoints()
macwbi.testPropertyInInterface()
macwbi.testPropertyInInterfaceImpl()
}
// EXPECTATIONS JVM JVM_IR
// test.kt:30 box
// test.kt:15 <init>
// test.kt:17 <init>
// test.kt:20 <init>
// EXPECTATIONS JVM_IR
// test.kt:15 <init>
// EXPECTATIONS JVM JVM_IR
// test.kt:30 box
// test.kt:31 box
// test.kt:15 testPropertyInInterface
// test.kt:8 testPropertyInInterface
// test.kt:17 getPropVal2
// test.kt:8 testPropertyInInterface
// test.kt:9 testPropertyInInterface
// test.kt:20 getPropVar2
// test.kt:9 testPropertyInInterface
// test.kt:10 testPropertyInInterface
// test.kt:20 setPropVar2
// test.kt:11 testPropertyInInterface
// test.kt:15 testPropertyInInterface
// test.kt:32 box
// test.kt:23 testPropertyInInterfaceImpl
// test.kt:17 getPropVal2
// test.kt:23 testPropertyInInterfaceImpl
// test.kt:24 testPropertyInInterfaceImpl
// test.kt:20 getPropVar2
// test.kt:24 testPropertyInInterfaceImpl
// test.kt:25 testPropertyInInterfaceImpl
// test.kt:20 setPropVar2
// test.kt:26 testPropertyInInterfaceImpl
// test.kt:33 box
// EXPECTATIONS JS_IR
// test.kt:30 box
// test.kt:17 <init>
// test.kt:20 <init>
// test.kt:15 <init>
// test.kt:31 box
// test.kt:8 testPropertyInInterface
// test.kt:17 <get-propVal2>
// test.kt:9 testPropertyInInterface
// test.kt:20 <get-propVar2>
// test.kt:10 testPropertyInInterface
// test.kt:20 <set-propVar2>
// test.kt:20 <set-propVar2>
// test.kt:11 testPropertyInInterface
// test.kt:32 box
// test.kt:25 testPropertyInInterfaceImpl
// test.kt:26 testPropertyInInterfaceImpl
// test.kt:33 box
@@ -85,6 +85,30 @@ public class IrSteppingWithBytecodeInlinerTestGenerated extends AbstractIrSteppi
runTest("compiler/testData/debug/stepping/classObject.kt");
}
@Test
@TestMetadata("commentBeforeClass.kt")
public void testCommentBeforeClass() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeClass.kt");
}
@Test
@TestMetadata("commentBeforeCompanionProperty.kt")
public void testCommentBeforeCompanionProperty() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeCompanionProperty.kt");
}
@Test
@TestMetadata("commentBeforeFunctionWithDefault.kt")
public void testCommentBeforeFunctionWithDefault() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeFunctionWithDefault.kt");
}
@Test
@TestMetadata("comments.kt")
public void testComments() throws Exception {
runTest("compiler/testData/debug/stepping/comments.kt");
}
@Test
@TestMetadata("compileTimeConstant.kt")
public void testCompileTimeConstant() throws Exception {
@@ -367,6 +391,12 @@ public class IrSteppingWithBytecodeInlinerTestGenerated extends AbstractIrSteppi
runTest("compiler/testData/debug/stepping/nullcheck.kt");
}
@Test
@TestMetadata("overridenGetterSetter.kt")
public void testOverridenGetterSetter() throws Exception {
runTest("compiler/testData/debug/stepping/overridenGetterSetter.kt");
}
@Test
@TestMetadata("primitiveNullChecks.kt")
public void testPrimitiveNullChecks() throws Exception {
@@ -85,6 +85,30 @@ public class IrSteppingWithIrInlinerTestGenerated extends AbstractIrSteppingWith
runTest("compiler/testData/debug/stepping/classObject.kt");
}
@Test
@TestMetadata("commentBeforeClass.kt")
public void testCommentBeforeClass() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeClass.kt");
}
@Test
@TestMetadata("commentBeforeCompanionProperty.kt")
public void testCommentBeforeCompanionProperty() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeCompanionProperty.kt");
}
@Test
@TestMetadata("commentBeforeFunctionWithDefault.kt")
public void testCommentBeforeFunctionWithDefault() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeFunctionWithDefault.kt");
}
@Test
@TestMetadata("comments.kt")
public void testComments() throws Exception {
runTest("compiler/testData/debug/stepping/comments.kt");
}
@Test
@TestMetadata("compileTimeConstant.kt")
public void testCompileTimeConstant() throws Exception {
@@ -367,6 +391,12 @@ public class IrSteppingWithIrInlinerTestGenerated extends AbstractIrSteppingWith
runTest("compiler/testData/debug/stepping/nullcheck.kt");
}
@Test
@TestMetadata("overridenGetterSetter.kt")
public void testOverridenGetterSetter() throws Exception {
runTest("compiler/testData/debug/stepping/overridenGetterSetter.kt");
}
@Test
@TestMetadata("primitiveNullChecks.kt")
public void testPrimitiveNullChecks() throws Exception {
@@ -85,6 +85,30 @@ public class SteppingTestGenerated extends AbstractSteppingTest {
runTest("compiler/testData/debug/stepping/classObject.kt");
}
@Test
@TestMetadata("commentBeforeClass.kt")
public void testCommentBeforeClass() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeClass.kt");
}
@Test
@TestMetadata("commentBeforeCompanionProperty.kt")
public void testCommentBeforeCompanionProperty() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeCompanionProperty.kt");
}
@Test
@TestMetadata("commentBeforeFunctionWithDefault.kt")
public void testCommentBeforeFunctionWithDefault() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeFunctionWithDefault.kt");
}
@Test
@TestMetadata("comments.kt")
public void testComments() throws Exception {
runTest("compiler/testData/debug/stepping/comments.kt");
}
@Test
@TestMetadata("compileTimeConstant.kt")
public void testCompileTimeConstant() throws Exception {
@@ -367,6 +391,12 @@ public class SteppingTestGenerated extends AbstractSteppingTest {
runTest("compiler/testData/debug/stepping/nullcheck.kt");
}
@Test
@TestMetadata("overridenGetterSetter.kt")
public void testOverridenGetterSetter() throws Exception {
runTest("compiler/testData/debug/stepping/overridenGetterSetter.kt");
}
@Test
@TestMetadata("primitiveNullChecks.kt")
public void testPrimitiveNullChecks() throws Exception {
@@ -85,6 +85,30 @@ public class IrJsSteppingTestGenerated extends AbstractIrJsSteppingTest {
runTest("compiler/testData/debug/stepping/classObject.kt");
}
@Test
@TestMetadata("commentBeforeClass.kt")
public void testCommentBeforeClass() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeClass.kt");
}
@Test
@TestMetadata("commentBeforeCompanionProperty.kt")
public void testCommentBeforeCompanionProperty() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeCompanionProperty.kt");
}
@Test
@TestMetadata("commentBeforeFunctionWithDefault.kt")
public void testCommentBeforeFunctionWithDefault() throws Exception {
runTest("compiler/testData/debug/stepping/commentBeforeFunctionWithDefault.kt");
}
@Test
@TestMetadata("comments.kt")
public void testComments() throws Exception {
runTest("compiler/testData/debug/stepping/comments.kt");
}
@Test
@TestMetadata("compileTimeConstant.kt")
public void testCompileTimeConstant() throws Exception {
@@ -367,6 +391,12 @@ public class IrJsSteppingTestGenerated extends AbstractIrJsSteppingTest {
runTest("compiler/testData/debug/stepping/nullcheck.kt");
}
@Test
@TestMetadata("overridenGetterSetter.kt")
public void testOverridenGetterSetter() throws Exception {
runTest("compiler/testData/debug/stepping/overridenGetterSetter.kt");
}
@Test
@TestMetadata("primitiveNullChecks.kt")
public void testPrimitiveNullChecks() throws Exception {
@@ -737,7 +737,7 @@ public abstract class Result : java/lang/Object, X {
private void <init>() {
LABEL (L0)
LINENUMBER (11)
LINENUMBER (12)
ALOAD (0)
INVOKESPECIAL (java/lang/Object, <init>, ()V)
RETURN
@@ -746,7 +746,7 @@ public abstract class Result : java/lang/Object, X {
public void <init>(int seen0, kotlinx.serialization.internal.SerializationConstructorMarker serializationConstructorMarker) {
LABEL (L0)
LINENUMBER (11)
LINENUMBER (12)
ALOAD (0)
INVOKESPECIAL (java/lang/Object, <init>, ()V)
RETURN