Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gui):improve search and usage dialog #2383

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 11 additions & 17 deletions jadx-gui/src/main/java/jadx/gui/search/ISearchMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,19 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

public interface ISearchMethod {
int find(String input, String subStr, int start);
MatchingPositions find(String input, int start);

static ISearchMethod build(SearchSettings searchSettings) {
if (searchSettings.isUseRegex()) {
Pattern pattern = searchSettings.getPattern();
return (input, subStr, start) -> {
Matcher matcher = pattern.matcher(input);
if (matcher.find(start)) {
return matcher.start();
}
return -1;
};
}
if (searchSettings.isIgnoreCase()) {
return StringUtils::indexOfIgnoreCase;
}
return String::indexOf;
Pattern pattern = searchSettings.getPattern();
return (input, start) -> {
Matcher matcher = pattern.matcher(input);
if (matcher.find(start)) {
int startIndex = matcher.start();
int endIndex = matcher.end();
return new MatchingPositions(/* lineText, */startIndex, endIndex);
}
return null;
};
}
}
50 changes: 50 additions & 0 deletions jadx-gui/src/main/java/jadx/gui/search/MatchingPositions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package jadx.gui.search;

public class MatchingPositions {
private final String line;
private int startMath;
private int endMath;

private int lineNumber;

public MatchingPositions(String line) {
this.line = line;
}

public MatchingPositions(String line, int lineNumber, int startMath, int endMath) {
this.line = line;
this.lineNumber = lineNumber;
this.startMath = startMath;
this.endMath = endMath;
}

public MatchingPositions(String line, int startMath, int endMath) {
this.line = line;
this.lineNumber = -1;
this.startMath = startMath;
this.endMath = endMath;
}

public MatchingPositions(int startMath, int endMath) {
this.line = null;
this.lineNumber = -1;
this.startMath = startMath;
this.endMath = endMath;
}

public int getLineNumber() {
return lineNumber;
}

public String getLine() {
return line;
}

public int getEndMath() {
return endMath;
}

public int getStartMath() {
return startMath;
}
}
39 changes: 39 additions & 0 deletions jadx-gui/src/main/java/jadx/gui/search/SearchManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package jadx.gui.search;

import java.util.regex.Pattern;

public class SearchManager {
/**
* Generate the good pattern according to the different boolean
*
* @param exp the searched expression
* @param caseSensitive boolean
* @param wholeWord boolean
* @param useRegexp boolean
* @return the pattern
*/
public static Pattern generatePattern(String exp, boolean caseSensitive, boolean wholeWord, boolean useRegexp) {
String word = exp;
if (word != null && !word.isEmpty()) {
if (!useRegexp) {
word = word.replace("\\E", "\\E\\\\E\\Q");
word = "\\Q" + word + "\\E";
if (wholeWord && exp.matches("\\b.*\\b")) {
word = "\\b" + word + "\\b";
}
}

if (!caseSensitive) {
word = "(?i)" + word;
}

if (useRegexp) {
word = "(?m)" + word;
}

return Pattern.compile(word);
} else {
return Pattern.compile("");
}
}
}
28 changes: 10 additions & 18 deletions jadx-gui/src/main/java/jadx/gui/search/SearchSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,44 +13,36 @@ public class SearchSettings {
private final String searchString;
private final boolean useRegex;
private final boolean ignoreCase;
private final boolean wholeWord;
private final JavaPackage searchPackage;

private JClass activeCls;
private JResource activeResource;
private Pattern regexPattern;
private ISearchMethod searchMethod;

public SearchSettings(String searchString, boolean ignoreCase, boolean useRegex, JavaPackage searchPackage) {
public SearchSettings(String searchString, boolean ignoreCase, boolean wholeWord, boolean useRegex, JavaPackage searchPackage) {
this.searchString = searchString;
this.useRegex = useRegex;
this.ignoreCase = ignoreCase;
this.wholeWord = wholeWord;
this.useRegex = useRegex;
this.searchPackage = searchPackage;
}

@Nullable
public String prepare() {
if (useRegex) {
try {
int flags = ignoreCase ? Pattern.CASE_INSENSITIVE : 0;
this.regexPattern = Pattern.compile(searchString, flags);
} catch (Exception e) {
return "Invalid Regex: " + e.getMessage();
}
try {
this.regexPattern = SearchManager.generatePattern(searchString, ignoreCase, wholeWord, useRegex);
} catch (Exception e) {
return "Invalid Regex: " + e.getMessage();
}

searchMethod = ISearchMethod.build(this);
return null;
}

public boolean isMatch(String searchArea) {
return searchMethod.find(searchArea, this.searchString, 0) != -1;
}

public boolean isUseRegex() {
return this.useRegex;
}

public boolean isIgnoreCase() {
return this.ignoreCase;
return searchMethod.find(searchArea, 0) != null;
}

public JavaPackage getSearchPackage() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import jadx.core.dex.nodes.ICodeNode;
import jadx.gui.search.ISearchMethod;
import jadx.gui.search.ISearchProvider;
import jadx.gui.search.MatchingPositions;
import jadx.gui.search.SearchSettings;
import jadx.gui.treemodel.JClass;
import jadx.gui.treemodel.JNode;
Expand Down Expand Up @@ -41,8 +42,8 @@ public BaseSearchProvider(MainWindow mw, SearchSettings searchSettings, List<Jav
this.searchSettings = searchSettings;
}

protected boolean isMatch(String str) {
return searchMth.find(str, searchStr, 0) != -1;
protected MatchingPositions isMatch(String str) {
return searchMth.find(str, 0);
}

protected JNode convert(JavaNode node) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import jadx.api.JavaClass;
import jadx.core.dex.info.ClassInfo;
import jadx.gui.jobs.Cancelable;
import jadx.gui.search.MatchingPositions;
import jadx.gui.search.SearchSettings;
import jadx.gui.treemodel.JNode;
import jadx.gui.ui.MainWindow;
Expand All @@ -26,18 +27,34 @@ public ClassSearchProvider(MainWindow mw, SearchSettings searchSettings, List<Ja
return null;
}
JavaClass curCls = classes.get(clsNum++);
if (checkCls(curCls)) {
return convert(curCls);
MatchingPositions matchingPositions = checkCls(curCls);
if (matchingPositions != null) {
JNode node = convert(curCls);
MatchingPositions highlightPositions = isMatch(curCls.getFullName());
node.setHasHighlight(true);
node.setStart(highlightPositions.getStartMath());
node.setEnd(highlightPositions.getEndMath());
return node;
}
}
}

private boolean checkCls(JavaClass cls) {
private MatchingPositions checkCls(JavaClass cls) {
ClassInfo clsInfo = cls.getClassNode().getClassInfo();
return isMatch(clsInfo.getShortName())
|| isMatch(clsInfo.getFullName())
|| isMatch(clsInfo.getAliasFullName())
|| isMatch(clsInfo.getRawName());
MatchingPositions shortMatch = isMatch(clsInfo.getShortName());
MatchingPositions fullMatch = isMatch(clsInfo.getFullName());
MatchingPositions aliasMatch = isMatch(clsInfo.getAliasFullName());
MatchingPositions rawMatch = isMatch(clsInfo.getRawName());
if (shortMatch != null) {
return shortMatch;
}
if (fullMatch != null) {
return fullMatch;
}
if (aliasMatch != null) {
return aliasMatch;
}
return rawMatch;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import jadx.api.utils.CodeUtils;
import jadx.gui.JadxWrapper;
import jadx.gui.jobs.Cancelable;
import jadx.gui.search.MatchingPositions;
import jadx.gui.search.SearchSettings;
import jadx.gui.treemodel.CodeNode;
import jadx.gui.treemodel.JClass;
Expand Down Expand Up @@ -64,18 +65,24 @@ public CodeSearchProvider(MainWindow mw, SearchSettings searchSettings, List<Jav

@Nullable
private JNode searchNext(JavaClass javaClass, String clsCode) {
int newPos = searchMth.find(clsCode, searchStr, pos);
if (newPos == -1) {
MatchingPositions positions = searchMth.find(clsCode, pos);
if (positions == null) {
return null;
}
int newPos = positions.getStartMath();
int lineStart = 1 + CodeUtils.getNewLinePosBefore(clsCode, newPos);
int lineEnd = CodeUtils.getNewLinePosAfter(clsCode, newPos);
int end = lineEnd == -1 ? clsCode.length() : lineEnd;
String line = clsCode.substring(lineStart, end);
String line = clsCode.substring(lineStart, end).trim();
this.pos = end;

// build pos for highlight
MatchingPositions highlightPositions = searchMth.find(line, 0);
int startHighlight = highlightPositions.getStartMath();
int endHighlight = highlightPositions.getEndMath();
JClass rootCls = convert(javaClass);
JNode enclosingNode = getOrElse(getEnclosingNode(javaClass, end), rootCls);
return new CodeNode(rootCls, enclosingNode, line.trim(), newPos);
return new CodeNode(rootCls, enclosingNode, line, newPos, startHighlight, endHighlight);
}

private @Nullable JNode getEnclosingNode(JavaClass javaCls, int pos) {
Expand Down
Loading
Loading