Reland "Change the kotlin debug parser to use segment trees for results"
This reverts commit bac0ccfd0fe9f33c328c2f4e463bb7773faa7df0.
Change-Id: Ib32e72917b9e2bb47f434c3abe6381a011c35c1c
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinSourceDebugExtensionParser.java b/src/main/java/com/android/tools/r8/kotlin/KotlinSourceDebugExtensionParser.java
index a0d4df2..8c6c2b8 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinSourceDebugExtensionParser.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinSourceDebugExtensionParser.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.kotlin;
import com.android.tools.r8.naming.Range;
+import com.android.tools.r8.utils.SegmentTree;
import com.android.tools.r8.utils.ThrowingConsumer;
import java.io.BufferedReader;
import java.io.Closeable;
@@ -211,9 +212,10 @@
private static void addDebugEntryToBuilder(String debugEntry, ResultBuilder builder)
throws KotlinSourceDebugExtensionParserException {
- // <from>#<file>,<to>:<debug-line-position>
+ // <from>#<file>,<size>:<debug-line-position>
// or
// <from>#<file>:<debug-line-position>
+ // All positions should define intervals for mappings.
try {
int targetSplit = debugEntry.indexOf(':');
int target = Integer.parseInt(debugEntry.substring(targetSplit + 1));
@@ -223,7 +225,7 @@
// The range may have a different end than start.
String fileAndEndRange = original.substring(fileIndexSplit + 1);
int endRangeCharPosition = fileAndEndRange.indexOf(',');
- int size = originalStart;
+ int size = 1;
if (endRangeCharPosition > -1) {
// The file should be at least one number wide.
assert endRangeCharPosition > 0;
@@ -233,16 +235,13 @@
}
int fileIndex = Integer.parseInt(fileAndEndRange.substring(0, endRangeCharPosition));
Source thisFileSource = builder.files.get(fileIndex);
- if (thisFileSource != null) {
- Range range = new Range(originalStart, originalStart + size);
- Position position = new Position(thisFileSource, range);
- Position existingPosition = builder.positions.put(target, position);
- assert existingPosition == null
- : "Position index "
- + target
- + " was already mapped to an existing position: "
- + position;
+ if (thisFileSource == null) {
+ throw new KotlinSourceDebugExtensionParserException(
+ "Could not find file with index " + fileIndex);
}
+ Range range = new Range(originalStart, originalStart + (size - 1));
+ Position position = new Position(thisFileSource, range);
+ builder.segmentTree.add(target, target + (size - 1), position);
} catch (NumberFormatException e) {
throw new KotlinSourceDebugExtensionParserException("Could not convert position to number");
}
@@ -250,29 +249,28 @@
public static class Result {
- private final Map<Integer, Source> files;
- private final Map<Integer, Position> positions;
+ private final SegmentTree<Position> segmentTree;
- private Result(Map<Integer, Source> files, Map<Integer, Position> positions) {
- this.files = files;
- this.positions = positions;
+ public Result(SegmentTree<Position> segmentTree) {
+ this.segmentTree = segmentTree;
}
- public Map<Integer, Source> getFiles() {
- return files;
+ public Map.Entry<Integer, Position> lookup(int point) {
+ return segmentTree.findEntry(point);
}
- public Map<Integer, Position> getPositions() {
- return positions;
+ public int size() {
+ return segmentTree.size();
}
}
public static class ResultBuilder {
- final Map<Integer, Source> files = new HashMap<>();
- final Map<Integer, Position> positions = new HashMap<>();
+
+ SegmentTree<Position> segmentTree = new SegmentTree<>(false);
+ Map<Integer, Source> files = new HashMap<>();
public Result build() {
- return new Result(files, positions);
+ return new Result(segmentTree);
}
}
@@ -326,6 +324,7 @@
sb.append(",");
sb.append(range.to);
}
+ sb.append(":");
return sb.toString();
}
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/KotlinSourceDebugExtensionParserTest.java b/src/test/java/com/android/tools/r8/kotlin/KotlinSourceDebugExtensionParserTest.java
index 6ad7046..d7ecc12 100644
--- a/src/test/java/com/android/tools/r8/kotlin/KotlinSourceDebugExtensionParserTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/KotlinSourceDebugExtensionParserTest.java
@@ -4,9 +4,7 @@
package com.android.tools.r8.kotlin;
-import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -15,9 +13,7 @@
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.kotlin.KotlinSourceDebugExtensionParser.Position;
import com.android.tools.r8.kotlin.KotlinSourceDebugExtensionParser.Result;
-import com.android.tools.r8.kotlin.KotlinSourceDebugExtensionParser.Source;
import com.android.tools.r8.utils.StringUtils;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -39,7 +35,6 @@
}
@Test
- @Ignore("b/145985445")
public void testParsingNoInlineSources() {
String annotationData =
StringUtils.join(
@@ -56,19 +51,16 @@
"*E");
Result result = KotlinSourceDebugExtensionParser.parse(annotationData);
assertNotNull(result);
- assertEquals(1, result.getFiles().size());
- Source source = result.getFiles().get(1);
- assertEquals("EnumSwitch.kt", source.getFileName());
- assertEquals("enumswitch/EnumSwitchKt", source.getPath());
- assertTrue(result.getPositions().containsKey(1));
- Position position = result.getPositions().get(1);
- assertEquals(source, position.getSource());
+ assertEquals(1, result.size());
+ assertEquals(1, (int) result.lookup(1).getKey());
+ Position position = result.lookup(1).getValue();
+ assertEquals("EnumSwitch.kt", position.getSource().getFileName());
+ assertEquals("enumswitch/EnumSwitchKt", position.getSource().getPath());
assertEquals(1, position.getRange().from);
assertEquals(38, position.getRange().to);
}
@Test
- @Ignore("b/145985445")
public void testParsingSimpleStrata() {
// Taken from src/test/examplesKotlin/retrace/mainKt
String annotationData =
@@ -100,32 +92,33 @@
"*E");
Result result = KotlinSourceDebugExtensionParser.parse(annotationData);
assertNotNull(result);
- assertEquals(3, result.getFiles().size());
+ assertEquals(3, result.size());
+ assertEquals(1, (int) result.lookup(1).getKey());
+ assertEquals(23, (int) result.lookup(23).getKey());
+ assertEquals(24, (int) result.lookup(24).getKey());
+
// Check that files are correctly parsed.
- Source source1 = result.getFiles().get(1);
- assertEquals("Main.kt", source1.getFileName());
- assertEquals("retrace/MainKt", source1.getPath());
+ Position pos1 = result.lookup(1).getValue();
+ assertEquals("Main.kt", pos1.getSource().getFileName());
+ assertEquals("retrace/MainKt", pos1.getSource().getPath());
- Source source2 = result.getFiles().get(2);
- assertEquals("InlineFunction.kt", source2.getFileName());
- assertEquals("retrace/InlineFunctionKt", source2.getPath());
+ Position pos2 = result.lookup(23).getValue();
+ assertEquals("InlineFunction.kt", pos2.getSource().getFileName());
+ assertEquals("retrace/InlineFunctionKt", pos2.getSource().getPath());
- Source source3 = result.getFiles().get(3);
- assertEquals("InlineFunction.kt", source3.getFileName());
- assertEquals("retrace/InlineFunction", source3.getPath());
+ Position pos3 = result.lookup(24).getValue();
+ assertEquals("InlineFunction.kt", pos3.getSource().getFileName());
+ assertEquals("retrace/InlineFunction", pos3.getSource().getPath());
// Check that the inline positions can be traced.
- assertTrue(result.getPositions().containsKey(23));
- Position position1 = result.getPositions().get(23);
- assertEquals(source2, position1.getSource());
- assertEquals(7, position1.getRange().from);
- assertEquals(7, position1.getRange().to);
+ assertEquals(1, pos1.getRange().from);
+ assertEquals(22, pos1.getRange().to);
- assertTrue(result.getPositions().containsKey(24));
- Position position2 = result.getPositions().get(24);
- assertEquals(source3, position2.getSource());
- assertEquals(12, position2.getRange().from);
- assertEquals(12, position2.getRange().to);
+ assertEquals(7, pos2.getRange().from);
+ assertEquals(7, pos2.getRange().to);
+
+ assertEquals(12, pos3.getRange().from);
+ assertEquals(12, pos3.getRange().to);
}
@Test
@@ -286,12 +279,43 @@
"7#2:23",
"12#4:24", // <-- non-existing file index
"*E");
+ assertNull(KotlinSourceDebugExtensionParser.parse(annotationData));
+ }
+
+ @Test
+ public void testRanges() {
+ String annotationData =
+ StringUtils.join(
+ "\n",
+ "SMAP",
+ "Main.kt",
+ "Kotlin",
+ "*S Kotlin",
+ "*F",
+ "+ 1 Main.kt",
+ "retrace/MainKt",
+ "+ 2 InlineFunction.kt",
+ "retrace/InlineFunctionKt",
+ "+ 3 InlineFunction.kt",
+ "retrace/InlineFunction",
+ "*L",
+ "1#1,22:1",
+ "7#2,1:23",
+ "12#3,2:24",
+ "*E",
+ "*S KotlinDebug",
+ "*F",
+ "+ 1 Main.kt",
+ "retrace/MainKt",
+ "*L",
+ "12#1:23",
+ "18#1:24",
+ "*E");
Result parsedResult = KotlinSourceDebugExtensionParser.parse(annotationData);
assertNotNull(parsedResult);
-
- assertEquals(2, parsedResult.getPositions().size());
- assertTrue(parsedResult.getPositions().containsKey(1));
- assertTrue(parsedResult.getPositions().containsKey(23));
- assertFalse(parsedResult.getPositions().containsKey(24));
+ assertEquals(24, (int) parsedResult.lookup(25).getKey());
+ Position value = parsedResult.lookup(25).getValue();
+ assertEquals(12, value.getRange().from);
+ assertEquals(13, value.getRange().to);
}
}