Skip to content

Commit 23d468b

Browse files
committed
DRAFT
1 parent 9329e98 commit 23d468b

File tree

3 files changed

+108
-13
lines changed

3 files changed

+108
-13
lines changed

dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/symbol/Scope.java

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@
44
import java.util.List;
55

66
public class Scope {
7+
8+
public static class LineRange {
9+
final int start;
10+
final int end;
11+
12+
public LineRange(int start, int end) {
13+
this.start = start;
14+
this.end = end;
15+
}
16+
}
17+
718
@Json(name = "scope_type")
819
private final ScopeType scopeType;
920

@@ -16,6 +27,12 @@ public class Scope {
1627
@Json(name = "end_line")
1728
private final int endLine;
1829

30+
@Json(name = "has_injectible_lines")
31+
private final boolean hasInjectibleLines;
32+
33+
@Json(name = "injectible_lines")
34+
private final List<LineRange> injectibleLines;
35+
1936
private final String name;
2037

2138
@Json(name = "language_specifics")
@@ -30,6 +47,8 @@ public Scope(
3047
int startLine,
3148
int endLine,
3249
String name,
50+
boolean hasInjectibleLines,
51+
List<LineRange> injectibleLines,
3352
LanguageSpecifics languageSpecifics,
3453
List<Symbol> symbols,
3554
List<Scope> scopes) {
@@ -38,6 +57,8 @@ public Scope(
3857
this.startLine = startLine;
3958
this.endLine = endLine;
4059
this.name = name;
60+
this.hasInjectibleLines = hasInjectibleLines;
61+
this.injectibleLines = injectibleLines;
4162
this.languageSpecifics = languageSpecifics;
4263
this.symbols = symbols;
4364
this.scopes = scopes;
@@ -63,6 +84,14 @@ public String getName() {
6384
return name;
6485
}
6586

87+
public boolean hasInjectibleLines() {
88+
return hasInjectibleLines;
89+
}
90+
91+
public List<LineRange> getInjectibleLines() {
92+
return injectibleLines;
93+
}
94+
6695
public LanguageSpecifics getLanguageSpecifics() {
6796
return languageSpecifics;
6897
}
@@ -110,6 +139,8 @@ public static class Builder {
110139
private final int startLine;
111140
private final int endLine;
112141
private String name;
142+
private boolean hasInjectibleLines;
143+
private List<LineRange> injectibleLines;
113144
private LanguageSpecifics languageSpecifics;
114145
private List<Symbol> symbols;
115146
private List<Scope> scopes;
@@ -126,6 +157,16 @@ public Builder name(String name) {
126157
return this;
127158
}
128159

160+
public Builder hasInjectibleLines(boolean hasInjectibleLines) {
161+
this.hasInjectibleLines = hasInjectibleLines;
162+
return this;
163+
}
164+
165+
public Builder injectibleLines(List<LineRange> injectibleLines) {
166+
this.injectibleLines = injectibleLines;
167+
return this;
168+
}
169+
129170
public Builder languageSpecifics(LanguageSpecifics languageSpecifics) {
130171
this.languageSpecifics = languageSpecifics;
131172
return this;
@@ -143,7 +184,7 @@ public Builder scopes(List<Scope> scopes) {
143184

144185
public Scope build() {
145186
return new Scope(
146-
scopeType, sourceFile, startLine, endLine, name, languageSpecifics, symbols, scopes);
187+
scopeType, sourceFile, startLine, endLine, name, hasInjectibleLines, injectibleLines, languageSpecifics, symbols, scopes);
147188
}
148189
}
149190
}

dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/symbol/SymbolExtractor.java

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
import java.util.Collection;
1111
import java.util.Collections;
1212
import java.util.HashMap;
13+
import java.util.HashSet;
1314
import java.util.LinkedHashMap;
1415
import java.util.List;
1516
import java.util.Map;
17+
import java.util.Set;
1618
import java.util.stream.Collectors;
1719
import org.objectweb.asm.ClassReader;
1820
import org.objectweb.asm.Label;
@@ -124,6 +126,8 @@ private static List<Scope> extractMethods(ClassNode classNode, String sourceFile
124126
.name(method.name)
125127
.scopes(varScopes)
126128
.symbols(methodSymbols)
129+
.hasInjectibleLines(!methodLineInfo.ranges.isEmpty())
130+
.injectibleLines(methodLineInfo.ranges)
127131
.languageSpecifics(methodSpecifics)
128132
.build();
129133
methodScopes.add(methodScope);
@@ -431,26 +435,44 @@ private static Scope maxScope(Scope scope1, Scope scope2) {
431435
: scope1;
432436
}
433437

434-
private static int getFirstLine(MethodNode methodNode) {
435-
AbstractInsnNode node = methodNode.instructions.getFirst();
436-
while (node != null) {
437-
if (node.getType() == AbstractInsnNode.LINE) {
438-
LineNumberNode lineNumberNode = (LineNumberNode) node;
439-
return lineNumberNode.line;
438+
static List<Scope.LineRange> buildRanges(List<Integer> sortedLineNo) {
439+
if (sortedLineNo.isEmpty()) {
440+
return Collections.emptyList();
441+
}
442+
List<Scope.LineRange> ranges = new ArrayList<>();
443+
int start = sortedLineNo.get(0);
444+
int previous = start;
445+
int i = 1;
446+
while (i < sortedLineNo.size()) {
447+
int currentLine = sortedLineNo.get(i);
448+
while (currentLine == previous + 1) {
449+
i++;
450+
previous++;
451+
if (i < sortedLineNo.size()) {
452+
currentLine = sortedLineNo.get(i);
453+
}
440454
}
441-
node = node.getNext();
455+
ranges.add(new Scope.LineRange(start, previous));
456+
start = currentLine;
457+
previous = start;
458+
i++;
442459
}
443-
return 0;
460+
ranges.add(new Scope.LineRange(start, previous));
461+
return ranges;
444462
}
445463

446464
private static MethodLineInfo extractMethodLineInfo(MethodNode methodNode) {
447465
Map<Label, Integer> map = new HashMap<>();
448-
int startLine = getFirstLine(methodNode);
449-
int maxLine = startLine;
466+
List<Integer> lineNo = new ArrayList<>();
467+
Set<Integer> dedupSet = new HashSet<>();
450468
AbstractInsnNode node = methodNode.instructions.getFirst();
469+
int maxLine = 0;
451470
while (node != null) {
452471
if (node.getType() == AbstractInsnNode.LINE) {
453472
LineNumberNode lineNumberNode = (LineNumberNode) node;
473+
if (dedupSet.add(lineNumberNode.line)) {
474+
lineNo.add(lineNumberNode.line);
475+
}
454476
maxLine = Math.max(lineNumberNode.line, maxLine);
455477
}
456478
if (node.getType() == AbstractInsnNode.LABEL) {
@@ -461,7 +483,10 @@ private static MethodLineInfo extractMethodLineInfo(MethodNode methodNode) {
461483
}
462484
node = node.getNext();
463485
}
464-
return new MethodLineInfo(startLine, maxLine, map);
486+
lineNo.sort(Integer::compareTo);
487+
int startLine = lineNo.isEmpty() ? 0 : lineNo.get(0);
488+
List<Scope.LineRange> ranges = buildRanges(lineNo);
489+
return new MethodLineInfo(startLine, maxLine, map, ranges);
465490
}
466491

467492
private static ClassNode parseClassFile(byte[] classfileBuffer) {
@@ -475,11 +500,14 @@ public static class MethodLineInfo {
475500
final int start;
476501
final int end;
477502
final Map<Label, Integer> lineMap;
503+
final List<Scope.LineRange> ranges;
478504

479-
public MethodLineInfo(int start, int end, Map<Label, Integer> lineMap) {
505+
public MethodLineInfo(int start, int end, Map<Label, Integer> lineMap, List<Scope.LineRange> ranges) {
480506
this.start = start;
481507
this.end = end;
482508
this.lineMap = lineMap;
509+
510+
this.ranges = ranges;
483511
}
484512
}
485513
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.datadog.debugger.symbol;
2+
3+
import java.util.Arrays;
4+
import java.util.List;
5+
6+
import static org.junit.jupiter.api.Assertions.*;
7+
8+
class SymbolExtractorTest {
9+
10+
void ranges() {
11+
List<Scope.LineRange> ranges = SymbolExtractor.buildRanges(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
12+
assertEquals(1, ranges.size());
13+
assertEquals(1, ranges.get(0).start);
14+
assertEquals(10, ranges.get(0).end);
15+
ranges = SymbolExtractor.buildRanges(Arrays.asList(1, 3, 5, 7, 9));
16+
assertEquals(5, ranges.size());
17+
assertEquals(1, ranges.get(0).start);
18+
assertEquals(1, ranges.get(0).end);
19+
assertEquals(1, ranges.get(0).start);
20+
assertEquals(1, ranges.get(0).end);
21+
}
22+
23+
private static void assertLineRange(Scope.LineRange range, int expectedStart, int expectedEnd) {
24+
25+
}
26+
}

0 commit comments

Comments
 (0)