Projects STRLCPY jadx Commits 15a76c48
🤬
  • feat(gui): add auto complete for jadx scripts

  • Loading...
  • Skylot committed 1 year ago
    15a76c48
    1 parent 4a072731
  • ■ ■ ■ ■ ■ ■
    jadx-gui/build.gradle
    skipped 7 lines
    8 8  dependencies {
    9 9   implementation(project(':jadx-core'))
    10 10   implementation(project(":jadx-cli"))
     11 + 
     12 + // jadx-script autocomplete support
     13 + implementation(project(":jadx-plugins::jadx-script:jadx-script-ide"))
     14 + implementation("org.jetbrains.kotlin:kotlin-scripting-common:1.7.20")
     15 + implementation 'com.fifesoft:autocomplete:3.3.0'
     16 + 
    11 17   implementation 'com.beust:jcommander:1.82'
    12 18   implementation 'ch.qos.logback:logback-classic:1.3.4'
    13 19   
    skipped 134 lines
  • ■ ■ ■ ■ ■ ■
    jadx-gui/src/main/java/jadx/gui/plugins/script/CompletionRenderer.java
     1 +package jadx.gui.plugins.script;
     2 + 
     3 +import javax.swing.JList;
     4 + 
     5 +import org.fife.ui.autocomplete.Completion;
     6 +import org.fife.ui.autocomplete.CompletionCellRenderer;
     7 + 
     8 +import jadx.gui.settings.JadxSettings;
     9 + 
     10 +import static jadx.gui.utils.UiUtils.escapeHtml;
     11 +import static jadx.gui.utils.UiUtils.fadeHtml;
     12 +import static jadx.gui.utils.UiUtils.wrapHtml;
     13 + 
     14 +public class CompletionRenderer extends CompletionCellRenderer {
     15 + 
     16 + public CompletionRenderer(JadxSettings settings) {
     17 + setDisplayFont(settings.getFont());
     18 + }
     19 + 
     20 + @Override
     21 + protected void prepareForOtherCompletion(JList list, Completion c, int index, boolean selected, boolean hasFocus) {
     22 + JadxScriptCompletion cmpl = (JadxScriptCompletion) c;
     23 + setText(wrapHtml(escapeHtml(cmpl.getInputText()) + " "
     24 + + fadeHtml(escapeHtml(cmpl.getSummary()))));
     25 + }
     26 +}
     27 + 
  • ■ ■ ■ ■ ■ ■
    jadx-gui/src/main/java/jadx/gui/plugins/script/JadxScriptCompleteProvider.java
     1 +package jadx.gui.plugins.script;
     2 + 
     3 +import java.awt.Point;
     4 +import java.util.ArrayList;
     5 +import java.util.Collections;
     6 +import java.util.HashMap;
     7 +import java.util.List;
     8 +import java.util.Map;
     9 +import java.util.Objects;
     10 +import java.util.stream.Collectors;
     11 + 
     12 +import javax.swing.Icon;
     13 +import javax.swing.text.BadLocationException;
     14 +import javax.swing.text.JTextComponent;
     15 + 
     16 +import org.fife.ui.autocomplete.Completion;
     17 +import org.fife.ui.autocomplete.CompletionProviderBase;
     18 +import org.fife.ui.autocomplete.ParameterizedCompletion;
     19 +import org.slf4j.Logger;
     20 +import org.slf4j.LoggerFactory;
     21 + 
     22 +import kotlin.script.experimental.api.ScriptDiagnostic;
     23 +import kotlin.script.experimental.api.SourceCode;
     24 +import kotlin.script.experimental.api.SourceCodeCompletionVariant;
     25 + 
     26 +import jadx.core.utils.ListUtils;
     27 +import jadx.core.utils.exceptions.JadxRuntimeException;
     28 +import jadx.gui.ui.codearea.AbstractCodeArea;
     29 +import jadx.gui.utils.Icons;
     30 +import jadx.plugins.script.ide.JadxScriptAutoComplete;
     31 +import jadx.plugins.script.ide.ScriptCompletionResult;
     32 + 
     33 +import static jadx.plugins.script.ide.CompleteKt.AUTO_COMPLETE_INSERT_STR;
     34 + 
     35 +public class JadxScriptCompleteProvider extends CompletionProviderBase {
     36 + private static final Logger LOG = LoggerFactory.getLogger(JadxScriptCompleteProvider.class);
     37 + 
     38 + private static final Map<String, Icon> ICONS_MAP = buildIconsMap();
     39 + 
     40 + private static Map<String, Icon> buildIconsMap() {
     41 + Map<String, Icon> map = new HashMap<>();
     42 + map.put("class", Icons.CLASS);
     43 + map.put("method", Icons.METHOD);
     44 + map.put("field", Icons.FIELD);
     45 + map.put("property", Icons.PROPERTY);
     46 + map.put("parameter", Icons.PARAMETER);
     47 + map.put("package", Icons.PACKAGE);
     48 + return map;
     49 + }
     50 + 
     51 + private final AbstractCodeArea codeArea;
     52 + 
     53 + public JadxScriptCompleteProvider(AbstractCodeArea codeArea) {
     54 + this.codeArea = codeArea;
     55 + }
     56 + 
     57 + private List<Completion> getCompletions() {
     58 + try {
     59 + String code = codeArea.getText();
     60 + int caretPos = codeArea.getCaretPosition();
     61 + JadxScriptAutoComplete scriptComplete = new JadxScriptAutoComplete(codeArea.getNode().getName());
     62 + ScriptCompletionResult result = scriptComplete.complete(code, caretPos);
     63 + int replacePos = getReplacePos(caretPos, result);
     64 + if (!result.getReports().isEmpty()) {
     65 + LOG.debug("Script completion reports: {}", result.getReports());
     66 + }
     67 + return convertCompletions(result.getCompletions(), code, replacePos);
     68 + } catch (Exception e) {
     69 + LOG.error("Code completion failed", e);
     70 + return Collections.emptyList();
     71 + }
     72 + }
     73 + 
     74 + private List<Completion> convertCompletions(List<SourceCodeCompletionVariant> completions, String code, int replacePos) {
     75 + if (completions.isEmpty()) {
     76 + return Collections.emptyList();
     77 + }
     78 + if (LOG.isDebugEnabled()) {
     79 + String cmplStr = completions.stream().map(SourceCodeCompletionVariant::toString).collect(Collectors.joining("\n"));
     80 + LOG.debug("Completions:\n{}", cmplStr);
     81 + }
     82 + int count = completions.size();
     83 + List<Completion> list = new ArrayList<>(count);
     84 + for (int i = 0; i < count; i++) {
     85 + SourceCodeCompletionVariant c = completions.get(i);
     86 + if (Objects.equals(c.getIcon(), "keyword")) {
     87 + // too many, not very useful
     88 + continue;
     89 + }
     90 + 
     91 + JadxScriptCompletion cmpl = new JadxScriptCompletion(this, count - i);
     92 + cmpl.setData(c.getText(), code, replacePos);
     93 + if (Objects.equals(c.getIcon(), "method") && !Objects.equals(c.getText(), c.getDisplayText())) {
     94 + // add method args details for methods
     95 + cmpl.setSummary(c.getDisplayText() + " " + c.getTail());
     96 + } else {
     97 + cmpl.setSummary(c.getTail());
     98 + }
     99 + cmpl.setToolTip(c.getDisplayText());
     100 + Icon icon = ICONS_MAP.get(c.getIcon());
     101 + cmpl.setIcon(icon != null ? icon : Icons.FILE);
     102 + list.add(cmpl);
     103 + }
     104 + return list;
     105 + }
     106 + 
     107 + private int getReplacePos(int caretPos, ScriptCompletionResult result) throws BadLocationException {
     108 + int lineRaw = codeArea.getLineOfOffset(caretPos);
     109 + int lineStart = codeArea.getLineStartOffset(lineRaw);
     110 + int line = lineRaw + 1;
     111 + int col = caretPos - lineStart + 1;
     112 + 
     113 + List<ScriptDiagnostic> reports = result.getReports();
     114 + ScriptDiagnostic cmplReport = ListUtils.filterOnlyOne(reports, r -> {
     115 + if (r.getSeverity() == ScriptDiagnostic.Severity.ERROR && r.getLocation() != null) {
     116 + SourceCode.Position start = r.getLocation().getStart();
     117 + return start.getLine() == line && r.getMessage().endsWith(AUTO_COMPLETE_INSERT_STR);
     118 + }
     119 + return false;
     120 + });
     121 + if (cmplReport == null) {
     122 + LOG.warn("Failed to find completion report in: {}", reports);
     123 + return caretPos;
     124 + }
     125 + reports.remove(cmplReport);
     126 + int reportCol = Objects.requireNonNull(cmplReport.getLocation()).getStart().getCol();
     127 + return caretPos - (col - reportCol);
     128 + }
     129 + 
     130 + @Override
     131 + public String getAlreadyEnteredText(JTextComponent comp) {
     132 + try {
     133 + int pos = codeArea.getCaretPosition();
     134 + return codeArea.getText(0, pos);
     135 + } catch (Exception e) {
     136 + throw new JadxRuntimeException("Failed to get text before caret", e);
     137 + }
     138 + }
     139 + 
     140 + @Override
     141 + public List<Completion> getCompletionsAt(JTextComponent comp, Point p) {
     142 + return getCompletions();
     143 + }
     144 + 
     145 + @Override
     146 + protected List<Completion> getCompletionsImpl(JTextComponent comp) {
     147 + return getCompletions();
     148 + }
     149 + 
     150 + @Override
     151 + public List<ParameterizedCompletion> getParameterizedCompletions(JTextComponent tc) {
     152 + return null;
     153 + }
     154 +}
     155 + 
  • ■ ■ ■ ■ ■ ■
    jadx-gui/src/main/java/jadx/gui/plugins/script/JadxScriptCompletion.java
     1 +package jadx.gui.plugins.script;
     2 + 
     3 +import javax.swing.Icon;
     4 +import javax.swing.text.JTextComponent;
     5 + 
     6 +import org.fife.ui.autocomplete.Completion;
     7 +import org.fife.ui.autocomplete.CompletionProvider;
     8 + 
     9 +public class JadxScriptCompletion implements Completion {
     10 + 
     11 + private final CompletionProvider provider;
     12 + private final int relevance;
     13 + 
     14 + private String input;
     15 + private String code;
     16 + private int replacePos;
     17 + private Icon icon;
     18 + private String summary;
     19 + private String toolTip;
     20 + 
     21 + public JadxScriptCompletion(CompletionProvider provider, int relevance) {
     22 + this.provider = provider;
     23 + this.relevance = relevance;
     24 + }
     25 + 
     26 + public void setData(String input, String code, int replacePos) {
     27 + this.input = input;
     28 + this.code = code;
     29 + this.replacePos = replacePos;
     30 + }
     31 + 
     32 + @Override
     33 + public String getInputText() {
     34 + return input;
     35 + }
     36 + 
     37 + @Override
     38 + public CompletionProvider getProvider() {
     39 + return provider;
     40 + }
     41 + 
     42 + @Override
     43 + public String getAlreadyEntered(JTextComponent comp) {
     44 + return provider.getAlreadyEnteredText(comp);
     45 + }
     46 + 
     47 + @Override
     48 + public int getRelevance() {
     49 + return relevance;
     50 + }
     51 + 
     52 + @Override
     53 + public String getReplacementText() {
     54 + return code.substring(0, replacePos) + input;
     55 + }
     56 + 
     57 + @Override
     58 + public Icon getIcon() {
     59 + return icon;
     60 + }
     61 + 
     62 + public void setIcon(Icon icon) {
     63 + this.icon = icon;
     64 + }
     65 + 
     66 + @Override
     67 + public String getSummary() {
     68 + return summary;
     69 + }
     70 + 
     71 + public void setSummary(String summary) {
     72 + this.summary = summary;
     73 + }
     74 + 
     75 + @Override
     76 + public String getToolTipText() {
     77 + return toolTip;
     78 + }
     79 + 
     80 + public void setToolTip(String toolTip) {
     81 + this.toolTip = toolTip;
     82 + }
     83 + 
     84 + @Override
     85 + public int compareTo(Completion other) {
     86 + return Integer.compare(relevance, other.getRelevance());
     87 + }
     88 + 
     89 + @Override
     90 + public String toString() {
     91 + return input;
     92 + }
     93 +}
     94 + 
  • ■ ■ ■ ■ ■ ■
    jadx-gui/src/main/java/jadx/gui/treemodel/JClass.java
    skipped 19 lines
    20 20  import jadx.gui.ui.dialog.RenameDialog;
    21 21  import jadx.gui.ui.panel.ContentPanel;
    22 22  import jadx.gui.utils.CacheObject;
     23 +import jadx.gui.utils.Icons;
    23 24  import jadx.gui.utils.NLS;
    24 25  import jadx.gui.utils.UiUtils;
    25 26   
    26 27  public class JClass extends JLoadableNode {
    27 28   private static final long serialVersionUID = -1239986875244097177L;
    28 29   
    29  - private static final ImageIcon ICON_CLASS = UiUtils.openSvgIcon("nodes/class");
    30 30   private static final ImageIcon ICON_CLASS_ABSTRACT = UiUtils.openSvgIcon("nodes/abstractClass");
    31 31   private static final ImageIcon ICON_CLASS_PUBLIC = UiUtils.openSvgIcon("nodes/publicClass");
    32 32   private static final ImageIcon ICON_CLASS_PRIVATE = UiUtils.openSvgIcon("nodes/privateClass");
    skipped 122 lines
    155 155   if (accessInfo.isPublic()) {
    156 156   return ICON_CLASS_PUBLIC;
    157 157   }
    158  - return ICON_CLASS;
     158 + return Icons.CLASS;
    159 159   }
    160 160   
    161 161   @Override
    skipped 66 lines
  • ■ ■ ■ ■ ■ ■
    jadx-gui/src/main/java/jadx/gui/treemodel/JField.java
    skipped 14 lines
    15 15  import jadx.core.dex.info.AccessInfo;
    16 16  import jadx.gui.ui.MainWindow;
    17 17  import jadx.gui.ui.dialog.RenameDialog;
    18  -import jadx.gui.utils.OverlayIcon;
     18 +import jadx.gui.utils.Icons;
    19 19  import jadx.gui.utils.UiUtils;
    20 20   
    21 21  public class JField extends JNode {
    22 22   private static final long serialVersionUID = 1712572192106793359L;
    23 23   
    24  - private static final ImageIcon ICON_FLD_DEF = UiUtils.openSvgIcon("nodes/field");
    25 24   private static final ImageIcon ICON_FLD_PRI = UiUtils.openSvgIcon("nodes/privateField");
    26 25   private static final ImageIcon ICON_FLD_PRO = UiUtils.openSvgIcon("nodes/protectedField");
    27 26   private static final ImageIcon ICON_FLD_PUB = UiUtils.openSvgIcon("nodes/publicField");
    skipped 37 lines
    65 64   @Override
    66 65   public Icon getIcon() {
    67 66   AccessInfo af = field.getAccessFlags();
    68  - OverlayIcon icon = UiUtils.makeIcon(af, ICON_FLD_PUB, ICON_FLD_PRI, ICON_FLD_PRO, ICON_FLD_DEF);
    69  - return icon;
     67 + return UiUtils.makeIcon(af, ICON_FLD_PUB, ICON_FLD_PRI, ICON_FLD_PRO, Icons.FIELD);
    70 68   }
    71 69   
    72 70   @Override
    skipped 73 lines
  • ■ ■ ■ ■ ■
    jadx-gui/src/main/java/jadx/gui/treemodel/JMethod.java
    skipped 22 lines
    23 23   
    24 24  public class JMethod extends JNode {
    25 25   private static final long serialVersionUID = 3834526867464663751L;
    26  - 
    27  - private static final ImageIcon ICON_METHOD = UiUtils.openSvgIcon("nodes/method");
    28 26   private static final ImageIcon ICON_METHOD_ABSTRACT = UiUtils.openSvgIcon("nodes/abstractMethod");
    29 27   private static final ImageIcon ICON_METHOD_PRIVATE = UiUtils.openSvgIcon("nodes/privateMethod");
    30 28   private static final ImageIcon ICON_METHOD_PROTECTED = UiUtils.openSvgIcon("nodes/protectedMethod");
    skipped 35 lines
    66 64   @Override
    67 65   public Icon getIcon() {
    68 66   AccessInfo accessFlags = mth.getAccessFlags();
    69  - Icon icon = ICON_METHOD;
     67 + Icon icon = Icons.METHOD;
    70 68   if (accessFlags.isAbstract()) {
    71 69   icon = ICON_METHOD_ABSTRACT;
    72 70   }
    skipped 149 lines
  • ■ ■ ■ ■ ■ ■
    jadx-gui/src/main/java/jadx/gui/treemodel/JPackage.java
    skipped 4 lines
    5 5  import java.util.List;
    6 6   
    7 7  import javax.swing.Icon;
    8  -import javax.swing.ImageIcon;
    9 8  import javax.swing.JPopupMenu;
    10 9   
    11 10  import jadx.api.JavaPackage;
    skipped 1 lines
    13 12  import jadx.gui.JadxWrapper;
    14 13  import jadx.gui.ui.MainWindow;
    15 14  import jadx.gui.ui.popupmenu.JPackagePopupMenu;
    16  -import jadx.gui.utils.UiUtils;
     15 +import jadx.gui.utils.Icons;
    17 16   
    18 17  public class JPackage extends JNode {
    19 18   private static final long serialVersionUID = -4120718634156839804L;
    20  - 
    21  - private static final ImageIcon PACKAGE_ICON = UiUtils.openSvgIcon("nodes/package");
    22 19   
    23 20   private String fullName;
    24 21   private String name;
    skipped 93 lines
    118 115   
    119 116   @Override
    120 117   public Icon getIcon() {
    121  - return PACKAGE_ICON;
     118 + return Icons.PACKAGE;
    122 119   }
    123 120   
    124 121   @Override
    skipped 35 lines
  • ■ ■ ■ ■ ■ ■
    jadx-gui/src/main/java/jadx/gui/ui/codearea/AbstractCodeArea.java
    skipped 19 lines
    20 20  import javax.swing.JMenuItem;
    21 21  import javax.swing.JPopupMenu;
    22 22  import javax.swing.JViewport;
     23 +import javax.swing.KeyStroke;
    23 24  import javax.swing.SwingUtilities;
    24 25  import javax.swing.event.CaretEvent;
    25 26  import javax.swing.event.CaretListener;
    skipped 3 lines
    29 30  import javax.swing.text.Caret;
    30 31  import javax.swing.text.DefaultCaret;
    31 32   
     33 +import org.fife.ui.autocomplete.AutoCompletion;
    32 34  import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory;
    33 35  import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
    34 36  import org.fife.ui.rsyntaxtextarea.Token;
    skipped 9 lines
    44 46  import jadx.api.ICodeInfo;
    45 47  import jadx.core.utils.StringUtils;
    46 48  import jadx.core.utils.exceptions.JadxRuntimeException;
     49 +import jadx.gui.plugins.script.CompletionRenderer;
     50 +import jadx.gui.plugins.script.JadxScriptCompleteProvider;
    47 51  import jadx.gui.settings.JadxSettings;
    48 52  import jadx.gui.treemodel.JClass;
    49 53  import jadx.gui.treemodel.JEditableNode;
     54 +import jadx.gui.treemodel.JInputScript;
    50 55  import jadx.gui.treemodel.JNode;
    51 56  import jadx.gui.ui.MainWindow;
    52 57  import jadx.gui.ui.panel.ContentPanel;
    skipped 48 lines
    101 106   JEditableNode editableNode = (JEditableNode) node;
    102 107   addSaveActions(editableNode);
    103 108   addChangeUpdates(editableNode);
     109 + if (node instanceof JInputScript) {
     110 + addAutoComplete(settings);
     111 + }
    104 112   } else {
    105 113   addCaretActions();
    106 114   addFastCopyAction();
    skipped 107 lines
    214 222   editableNode.setChanged(true);
    215 223   }
    216 224   }));
     225 + }
     226 + 
     227 + private void addAutoComplete(JadxSettings settings) {
     228 + JadxScriptCompleteProvider provider = new JadxScriptCompleteProvider(this);
     229 + provider.setAutoActivationRules(false, ".");
     230 + AutoCompletion ac = new AutoCompletion(provider);
     231 + ac.setListCellRenderer(new CompletionRenderer(settings));
     232 + ac.setTriggerKey(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, UiUtils.ctrlButton()));
     233 + ac.setAutoActivationEnabled(true);
     234 + ac.setAutoCompleteSingleChoices(true);
     235 + ac.install(this);
    217 236   }
    218 237   
    219 238   private String highlightCaretWord(String lastText, int pos) {
    skipped 237 lines
  • ■ ■ ■ ■ ■
    jadx-gui/src/main/java/jadx/gui/ui/dialog/ExcludePkgDialog.java
    skipped 17 lines
    18 18   
    19 19  import javax.swing.BorderFactory;
    20 20  import javax.swing.BoxLayout;
    21  -import javax.swing.ImageIcon;
    22 21  import javax.swing.JButton;
    23 22  import javax.swing.JCheckBox;
    24 23  import javax.swing.JDialog;
    skipped 8 lines
    33 32   
    34 33  import jadx.api.JavaPackage;
    35 34  import jadx.gui.ui.MainWindow;
     35 +import jadx.gui.utils.Icons;
    36 36  import jadx.gui.utils.NLS;
    37 37  import jadx.gui.utils.UiUtils;
    38 38   
    39 39  public class ExcludePkgDialog extends JDialog {
    40 40   private static final long serialVersionUID = -1111111202104151030L;
    41  - private static final ImageIcon PACKAGE_ICON = UiUtils.openSvgIcon("nodes/package");
    42 41   
    43 42   private final transient MainWindow mainWindow;
    44 43   private transient JTree tree;
    skipped 266 lines
    311 310   return node.checkbox;
    312 311   }
    313 312   Component c = super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
    314  - setIcon(PACKAGE_ICON);
     313 + setIcon(Icons.PACKAGE);
    315 314   return c;
    316 315   }
    317 316   }
    skipped 2 lines
  • ■ ■ ■ ■ ■ ■
    jadx-gui/src/main/java/jadx/gui/utils/Icons.java
    skipped 19 lines
    20 20   
    21 21   public static final ImageIcon FOLDER = UiUtils.openSvgIcon("nodes/folder");
    22 22   public static final ImageIcon FILE = UiUtils.openSvgIcon("nodes/file_any_type");
     23 + 
     24 + public static final ImageIcon PACKAGE = UiUtils.openSvgIcon("nodes/package");
     25 + public static final ImageIcon CLASS = UiUtils.openSvgIcon("nodes/class");
     26 + public static final ImageIcon METHOD = UiUtils.openSvgIcon("nodes/method");
     27 + public static final ImageIcon FIELD = UiUtils.openSvgIcon("nodes/field");
     28 + public static final ImageIcon PROPERTY = UiUtils.openSvgIcon("nodes/property");
     29 + public static final ImageIcon PARAMETER = UiUtils.openSvgIcon("nodes/parameter");
    23 30  }
    24 31   
  • jadx-gui/src/main/resources/icons/nodes/parameter.svg
  • jadx-gui/src/main/resources/icons/nodes/property.svg
  • ■ ■ ■ ■ ■ ■
    jadx-plugins/jadx-script/jadx-script-ide/build.gradle.kts
     1 +plugins {
     2 + kotlin("jvm") version "1.7.20"
     3 +}
     4 + 
     5 +dependencies {
     6 + implementation("org.jetbrains.kotlin:kotlin-scripting-common")
     7 + implementation("org.jetbrains.kotlin:kotlin-scripting-jvm")
     8 + implementation("org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable")
     9 + implementation("org.jetbrains.kotlin:kotlin-scripting-ide-services")
     10 + 
     11 + implementation(project(":jadx-plugins:jadx-script:jadx-script-runtime"))
     12 + implementation(project(":jadx-plugins:jadx-script:jadx-script-plugin"))
     13 + 
     14 + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
     15 + implementation("io.github.microutils:kotlin-logging-jvm:3.0.2")
     16 +}
     17 + 
  • ■ ■ ■ ■ ■ ■
    jadx-plugins/jadx-script/jadx-script-ide/src/main/kotlin/complete.kt
     1 +package jadx.plugins.script.ide
     2 + 
     3 +import jadx.plugins.script.runner.ScriptEval
     4 +import kotlinx.coroutines.runBlocking
     5 +import org.jetbrains.kotlin.scripting.ide_services.compiler.KJvmReplCompilerWithIdeServices
     6 +import kotlin.script.experimental.api.*
     7 +import kotlin.script.experimental.host.toScriptSource
     8 +import kotlin.script.experimental.jvm.util.toSourceCodePosition
     9 + 
     10 +const val AUTO_COMPLETE_INSERT_STR = "ABCDEF" // defined at KJvmReplCompleter.INSERTED_STRING
     11 + 
     12 +data class ScriptCompletionResult(
     13 + val completions: List<SourceCodeCompletionVariant>,
     14 + val reports: List<ScriptDiagnostic>
     15 +)
     16 + 
     17 +class JadxScriptAutoComplete(private val scriptName: String) {
     18 + private val replCompiler = KJvmReplCompilerWithIdeServices()
     19 + private val compileConf = ScriptEval().buildCompileConf()
     20 + 
     21 + fun complete(code: String, cursor: Int): ScriptCompletionResult {
     22 + val result = complete(code.toScriptSource(scriptName), cursor)
     23 + return ScriptCompletionResult(
     24 + completions = result.valueOrNull()?.toList() ?: listOf(),
     25 + reports = result.reports
     26 + )
     27 + }
     28 + 
     29 + private fun complete(code: SourceCode, cursor: Int): ResultWithDiagnostics<ReplCompletionResult> {
     30 + return runBlocking {
     31 + replCompiler.complete(code, cursor.toSourceCodePosition(code), compileConf)
     32 + }
     33 + }
     34 +}
     35 + 
  • ■ ■ ■ ■ ■ ■
    jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/runner/ScriptEval.kt
    skipped 1 lines
    2 2   
    3 3  import jadx.api.JadxDecompiler
    4 4  import jadx.api.plugins.JadxPluginContext
    5  -import jadx.api.plugins.pass.JadxPassContext
    6 5  import jadx.plugins.script.runtime.JadxScript
    7 6  import jadx.plugins.script.runtime.JadxScriptData
    8 7  import mu.KotlinLogging
    skipped 29 lines
    38 37   processEvalResult(result, scriptFile)
    39 38   }
    40 39   
    41  - private fun eval(scriptFile: File, scriptData: JadxScriptData): ResultWithDiagnostics<EvaluationResult> {
    42  - val compilationConf = createJvmCompilationConfigurationFromTemplate<JadxScript>()
    43  - val evalConf = createJvmEvaluationConfigurationFromTemplate<JadxScript> {
     40 + fun buildCompileConf() = createJvmCompilationConfigurationFromTemplate<JadxScript>()
     41 + 
     42 + fun buildEvalConf(scriptData: JadxScriptData): ScriptEvaluationConfiguration {
     43 + return createJvmEvaluationConfigurationFromTemplate<JadxScript> {
    44 44   constructorArgs(scriptData)
    45 45   }
     46 + }
     47 + 
     48 + private fun eval(scriptFile: File, scriptData: JadxScriptData): ResultWithDiagnostics<EvaluationResult> {
     49 + val compilationConf = buildCompileConf()
     50 + val evalConf = buildEvalConf(scriptData)
    46 51   return BasicJvmScriptingHost().eval(scriptFile.toScriptSource(), compilationConf, evalConf)
    47 52   }
    48 53   
    skipped 20 lines
  • ■ ■ ■ ■ ■ ■
    jadx-plugins/jadx-script/jadx-script-runtime/build.gradle.kts
    skipped 3 lines
    4 4   kotlin("jvm") version "1.7.20"
    5 5  }
    6 6   
    7  -group = "jadx-script-context"
    8  - 
    9 7  dependencies {
    10 8   implementation("org.jetbrains.kotlin:kotlin-scripting-common")
    11 9   implementation("org.jetbrains.kotlin:kotlin-scripting-jvm")
    skipped 19 lines
  • ■ ■ ■ ■ ■
    settings.gradle.kts
    skipped 13 lines
    14 14   
    15 15  include("jadx-plugins:jadx-script:jadx-script-plugin")
    16 16  include("jadx-plugins:jadx-script:jadx-script-runtime")
     17 +include("jadx-plugins:jadx-script:jadx-script-ide")
    17 18  include("jadx-plugins:jadx-script:examples")
    18 19   
Please wait...
Page is in error, reload to recover