[bytecode viewer] fix caret position bugs

Invoking on line 7 now opens viewer on LINENUMBER 7, not LINENUMBER 6 (zero-based numbering problem) nor LINENUMBER 70 (poor indexof search).

Also get rid of one extra indexOf(lineNumber + 0) call.

Also remove buggy second iteration over lineNumbers in case of mapping presense.

GitOrigin-RevId: 1eba1545162eee37b566ba8bf834d24e7bf476c1
This commit is contained in:
Vladimir Parfinenko
2023-04-12 19:34:59 +02:00
committed by intellij-monorepo-bot
parent 63aad3ea69
commit a633c2f27c
2 changed files with 28 additions and 12 deletions

View File

@@ -6,7 +6,7 @@ import org.jetbrains.annotations.NotNull;
public interface LineNumbersMapping {
/**
* A mapping between lines contained in a byte code and actual source lines
* A mapping between lines contained in a byte code and actual source lines in IDE
* (placed into a user data of a VirtualFile for a .class file).
*/
Key<LineNumbersMapping> LINE_NUMBERS_MAPPING_KEY = Key.create("line.numbers.mapping.key");

View File

@@ -69,31 +69,47 @@ public class ByteCodeViewerComponent extends JPanel implements Disposable {
}
public void setText(@NonNls final String bytecode, PsiElement element) {
int offset = 0;
int offset = -1;
VirtualFile file = PsiUtilCore.getVirtualFile(element);
if (file != null) {
final Document document = FileDocumentManager.getInstance().getDocument(file);
if (document != null) {
int lineNumber = document.getLineNumber(element.getTextOffset());
int lineNumber = document.getLineNumber(element.getTextOffset()) + 1;
LineNumbersMapping mapping = file.getUserData(LineNumbersMapping.LINE_NUMBERS_MAPPING_KEY);
if (mapping != null) {
int mappedLine = mapping.sourceToBytecode(lineNumber);
while (mappedLine == -1 && lineNumber < document.getLineCount()) {
mappedLine = mapping.sourceToBytecode(++lineNumber);
}
if (mappedLine > 0) {
lineNumber = mappedLine;
for (int l = lineNumber; l <= document.getLineCount(); l++) {
int bytecodeLine = mapping.sourceToBytecode(l);
if (bytecodeLine != -1) {
offset = findLineNumber(bytecode, bytecodeLine);
assert offset != -1 : "there is bytecode line in mapping but it is missing in bytecode";
break;
}
}
}
offset = bytecode.indexOf("LINENUMBER " + lineNumber);
while (offset == -1 && lineNumber < document.getLineCount()) {
offset = bytecode.indexOf("LINENUMBER " + (lineNumber++));
else {
for (int l = lineNumber; l <= document.getLineCount(); l++) {
offset = findLineNumber(bytecode, l);
if (offset != -1) {
break;
}
}
}
}
}
setText(bytecode, Math.max(0, offset));
}
private static int findLineNumber(@NonNls String bytecode, int l) {
int idx = bytecode.indexOf("\n LINENUMBER " + l + " ");
if (idx != -1) {
// shift by one to skip '\n'
return idx + 1;
} else {
return -1;
}
}
public void setText(final String bytecode, final int offset) {
DocumentUtil.writeInRunUndoTransparentAction(() -> {
Document fragmentDoc = myEditor.getDocument();