mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-127182 (passing line number map to debugger)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.debugger;
|
||||
|
||||
import com.intellij.debugger.requests.ClassPrepareRequestor;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.sun.jdi.Location;
|
||||
import com.sun.jdi.ReferenceType;
|
||||
import com.sun.jdi.request.ClassPrepareRequest;
|
||||
@@ -31,6 +32,12 @@ import java.util.List;
|
||||
* @see com.intellij.debugger.engine.JSR45PositionManager
|
||||
*/
|
||||
public interface PositionManager {
|
||||
/**
|
||||
* A mapping between lines contained in a byte code and actual source lines
|
||||
* (placed into a user data of a VirtualFile for a .class file).
|
||||
*/
|
||||
Key<int[]> LINE_NUMBERS_MAPPING_KEY = Key.create("line.numbers.mapping.key");
|
||||
|
||||
/**
|
||||
* Returns the source position corresponding to the specified bytecode location.
|
||||
*
|
||||
|
||||
@@ -453,7 +453,11 @@ new.css.schema.enabled=true
|
||||
editor.disable.rtl=false
|
||||
editor.disable.rtl.description=Disables RTL support in editor (which is broken now anyway)
|
||||
|
||||
decompiler.use.line.mapping=false
|
||||
decompiler.use.line.mapping.description=Maps original to decompiled line numbers when stepping in debugger.
|
||||
decompiler.use.line.table=false
|
||||
decompiler.use.line.table.description=Rearranges decompiled text to match original line numbers
|
||||
|
||||
ide.transparency.mode.for.windows=false
|
||||
ide.transparency.mode.for.windows.description=Allow to add transparency to floating windows
|
||||
ide.new.welcome.screen=false
|
||||
|
||||
+1
-1
@@ -181,7 +181,7 @@ public class ConsoleDecompiler implements IBytecodeProvider, IResultSaver {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveClassFile(String path, String qualifiedName, String entryName, String content) {
|
||||
public void saveClassFile(String path, String qualifiedName, String entryName, String content, int[] mapping) {
|
||||
File file = new File(getAbsolutePath(path), entryName);
|
||||
try {
|
||||
Writer out = new OutputStreamWriter(new FileOutputStream(file), "UTF8");
|
||||
|
||||
Vendored
+1
-1
@@ -22,7 +22,7 @@ public interface IResultSaver {
|
||||
|
||||
void copyFile(String source, String path, String entryName);
|
||||
|
||||
void saveClassFile(String path, String qualifiedName, String entryName, String content);
|
||||
void saveClassFile(String path, String qualifiedName, String entryName, String content, int[] mapping);
|
||||
|
||||
void createArchive(String path, String archiveName, Manifest manifest);
|
||||
|
||||
|
||||
+7
-1
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.jetbrains.java.decompiler.struct;
|
||||
|
||||
import org.jetbrains.java.decompiler.main.DecompilerContext;
|
||||
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
|
||||
import org.jetbrains.java.decompiler.main.extern.IResultSaver;
|
||||
import org.jetbrains.java.decompiler.struct.lazy.LazyLoader;
|
||||
import org.jetbrains.java.decompiler.struct.lazy.LazyLoader.Link;
|
||||
@@ -112,7 +114,11 @@ public class ContextUnit {
|
||||
if (entryName != null) {
|
||||
String content = decompiledData.getClassContent(cl);
|
||||
if (content != null) {
|
||||
resultSaver.saveClassFile(filename, cl.qualifiedName, entryName, content);
|
||||
int[] mapping = null;
|
||||
if (DecompilerContext.getOption(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING)) {
|
||||
mapping = DecompilerContext.getBytecodeSourceMapper().getOriginalLinesMapping();
|
||||
}
|
||||
resultSaver.saveClassFile(filename, cl.qualifiedName, entryName, content, mapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<orderEntry type="module" module-name="java-psi-impl" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
<orderEntry type="module" module-name="platform-impl" />
|
||||
<orderEntry type="module" module-name="debugger-openapi" />
|
||||
<orderEntry type="module" module-name="testFramework-java" scope="TEST" />
|
||||
</component>
|
||||
</module>
|
||||
+19
-2
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.jetbrains.java.decompiler;
|
||||
|
||||
import com.intellij.debugger.PositionManager;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.ide.plugins.PluginManagerCore;
|
||||
@@ -146,13 +147,27 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light {
|
||||
MyBytecodeProvider provider = new MyBytecodeProvider(files);
|
||||
MyResultSaver saver = new MyResultSaver();
|
||||
|
||||
myOptions.put(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS, Registry.is("decompiler.use.line.table") ? "1" : "0");
|
||||
if (Registry.is("decompiler.use.line.mapping")) {
|
||||
myOptions.put(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1");
|
||||
myOptions.put(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS, "0");
|
||||
}
|
||||
else if (Registry.is("decompiler.use.line.table")) {
|
||||
myOptions.put(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "0");
|
||||
myOptions.put(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS, "1");
|
||||
}
|
||||
else {
|
||||
myOptions.put(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "0");
|
||||
myOptions.put(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS, "0");
|
||||
}
|
||||
|
||||
BaseDecompiler decompiler = new BaseDecompiler(provider, saver, myOptions, myLogger);
|
||||
for (String path : files.keySet()) {
|
||||
decompiler.addSpace(new File(path), true);
|
||||
}
|
||||
decompiler.decompileContext();
|
||||
|
||||
file.putUserData(PositionManager.LINE_NUMBERS_MAPPING_KEY, saver.myMapping);
|
||||
|
||||
return saver.myResult;
|
||||
}
|
||||
catch (Exception e) {
|
||||
@@ -190,11 +205,13 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light {
|
||||
|
||||
private static class MyResultSaver implements IResultSaver {
|
||||
private String myResult = "";
|
||||
private int[] myMapping = null;
|
||||
|
||||
@Override
|
||||
public void saveClassFile(String path, String qualifiedName, String entryName, String content) {
|
||||
public void saveClassFile(String path, String qualifiedName, String entryName, String content, int[] mapping) {
|
||||
if (myResult.isEmpty()) {
|
||||
myResult = content;
|
||||
myMapping = mapping;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+24
-1
@@ -17,9 +17,12 @@ package org.jetbrains.java.decompiler;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.IdentifierHighlighterPassFactory;
|
||||
import com.intellij.codeInsight.navigation.actions.GotoDeclarationAction;
|
||||
import com.intellij.debugger.PositionManager;
|
||||
import com.intellij.openapi.application.PluginPathManager;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.registry.RegistryValue;
|
||||
import com.intellij.openapi.vfs.StandardFileSystems;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -119,7 +122,7 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase {
|
||||
|
||||
private static VirtualFile getTestFile(String name) {
|
||||
String path = PluginPathManager.getPluginHomePath("java-decompiler") + "/plugin/testData/" + name;
|
||||
VirtualFile file = StandardFileSystems.local().findFileByPath(path);
|
||||
VirtualFile file = StandardFileSystems.local().refreshAndFindFileByPath(path);
|
||||
assertNotNull(path, file);
|
||||
return file;
|
||||
}
|
||||
@@ -135,4 +138,24 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase {
|
||||
private int offset(int line, int column) {
|
||||
return myFixture.getEditor().getDocument().getLineStartOffset(line - 1) + column - 1;
|
||||
}
|
||||
|
||||
public void testLineNumberMapping() {
|
||||
RegistryValue value = Registry.get("decompiler.use.line.mapping");
|
||||
boolean old = value.asBoolean();
|
||||
try {
|
||||
value.setValue(true);
|
||||
|
||||
VirtualFile file = getTestFile("LineNumbers.class");
|
||||
assertNull(file.getUserData(PositionManager.LINE_NUMBERS_MAPPING_KEY));
|
||||
|
||||
new IdeaDecompiler().getText(file);
|
||||
|
||||
int[] mapping = file.getUserData(PositionManager.LINE_NUMBERS_MAPPING_KEY);
|
||||
assertNotNull(mapping);
|
||||
assertEquals(20, mapping.length);
|
||||
}
|
||||
finally {
|
||||
value.setValue(old);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,16 @@
|
||||
class LineNumbers {
|
||||
void m(double a, double b, double c) {
|
||||
double d = b*b - 4*a*c;
|
||||
if (d < 0) {
|
||||
System.out.println("No roots.");
|
||||
} else if (d == 0) {
|
||||
double x = -b / 2*a;
|
||||
System.out.println("x=" + x);
|
||||
} else {
|
||||
d = Math.sqrt(d);
|
||||
double x1 = -b - d / 2*a;
|
||||
double x2 = -b + d / 2*a;
|
||||
System.out.println("x1=" + x1 + " x2=" + x2);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user