提交 b873c6ae 编写于 作者: S Skylot

refactor: use interface for CodeWriter

Details:
- add simple and annotated code writers to allow
   skip code annotations processing in jadx-cli and other places
- add annotated code info to use only than needed
- allow to set provider for codewriter in JadxArgs
- add JadxArgs argument to constructor to allow change output
- add cli option to insert debug line numbers as code comments
   (example for previous change)
上级 4835b1b8
......@@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory;
import jadx.api.JadxArgs;
import jadx.api.JadxDecompiler;
import jadx.api.impl.NoOpCodeCache;
import jadx.api.impl.SimpleCodeWriter;
import jadx.core.utils.exceptions.JadxArgsValidateException;
import jadx.core.utils.files.FileUtils;
......@@ -38,6 +39,7 @@ public class JadxCLI {
private static int processAndSave(JadxArgs jadxArgs) {
jadxArgs.setCodeCache(new NoOpCodeCache());
jadxArgs.setCodeWriterProvider(SimpleCodeWriter::new);
try (JadxDecompiler jadx = new JadxDecompiler(jadxArgs)) {
jadx.load();
jadx.save();
......
......@@ -58,6 +58,9 @@ public class JadxCLIArgs {
@Parameter(names = { "--no-debug-info" }, description = "disable debug info")
protected boolean debugInfo = true;
@Parameter(names = { "--add-debug-lines" }, description = "add comments with debug line numbers if available")
protected boolean addDebugLines = false;
@Parameter(names = { "--no-inline-anonymous" }, description = "disable anonymous classes inline")
protected boolean inlineAnonymousClasses = true;
......@@ -210,6 +213,7 @@ public class JadxCLIArgs {
args.setExportAsGradleProject(exportAsGradleProject);
args.setUseImports(useImports);
args.setDebugInfo(debugInfo);
args.setInsertDebugLines(addDebugLines);
args.setInlineAnonymousClasses(inlineAnonymousClasses);
args.setRenameCaseSensitive(isRenameCaseSensitive());
args.setRenameValid(isRenameValid());
......@@ -262,6 +266,10 @@ public class JadxCLIArgs {
return debugInfo;
}
public boolean isAddDebugLines() {
return addDebugLines;
}
public boolean isInlineAnonymousClasses() {
return inlineAnonymousClasses;
}
......
package jadx.api;
import jadx.core.dex.attributes.nodes.LineAttrNode;
public interface ICodeWriter {
String NL = System.getProperty("line.separator");
String INDENT_STR = " ";
boolean isMetadataSupported();
ICodeWriter startLine();
ICodeWriter startLine(char c);
ICodeWriter startLine(String str);
ICodeWriter startLineWithNum(int sourceLine);
ICodeWriter addMultiLine(String str);
ICodeWriter add(String str);
ICodeWriter add(char c);
ICodeWriter add(ICodeWriter code);
ICodeWriter newLine();
ICodeWriter addIndent();
void incIndent();
void decIndent();
int getIndent();
void setIndent(int indent);
int getLine();
void attachDefinition(LineAttrNode obj);
void attachAnnotation(Object obj);
void attachLineAnnotation(Object obj);
void attachSourceLine(int sourceLine);
ICodeInfo finish();
String getCodeStr();
int getLength();
}
......@@ -6,8 +6,10 @@ import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import jadx.api.impl.AnnotatedCodeWriter;
import jadx.api.impl.InMemoryCodeCache;
public class JadxArgs {
......@@ -25,6 +27,7 @@ public class JadxArgs {
private File outDirRes;
private ICodeCache codeCache = new InMemoryCodeCache();
private Function<JadxArgs, ICodeWriter> codeWriterProvider = AnnotatedCodeWriter::new;
private int threadsCount = DEFAULT_THREADS_COUNT;
......@@ -36,6 +39,7 @@ public class JadxArgs {
private boolean useImports = true;
private boolean debugInfo = true;
private boolean insertDebugLines = false;
private boolean inlineAnonymousClasses = true;
private boolean skipResources = false;
......@@ -176,6 +180,14 @@ public class JadxArgs {
this.debugInfo = debugInfo;
}
public boolean isInsertDebugLines() {
return insertDebugLines;
}
public void setInsertDebugLines(boolean insertDebugLines) {
this.insertDebugLines = insertDebugLines;
}
public boolean isInlineAnonymousClasses() {
return inlineAnonymousClasses;
}
......@@ -364,6 +376,14 @@ public class JadxArgs {
this.codeCache = codeCache;
}
public Function<JadxArgs, ICodeWriter> getCodeWriterProvider() {
return codeWriterProvider;
}
public void setCodeWriterProvider(Function<JadxArgs, ICodeWriter> codeWriterProvider) {
this.codeWriterProvider = codeWriterProvider;
}
@Override
public String toString() {
return "JadxArgs{" + "inputFiles=" + inputFiles
......@@ -393,6 +413,7 @@ public class JadxArgs {
+ ", renameFlags=" + renameFlags
+ ", outputFormat=" + outputFormat
+ ", codeCache=" + codeCache
+ ", codeWriter=" + codeWriterProvider.apply(this).getClass().getSimpleName()
+ '}';
}
}
......@@ -17,7 +17,6 @@ import org.slf4j.LoggerFactory;
import jadx.api.ResourceFile.ZipRef;
import jadx.api.impl.SimpleCodeInfo;
import jadx.api.plugins.utils.ZipSecurity;
import jadx.core.codegen.CodeWriter;
import jadx.core.utils.Utils;
import jadx.core.utils.android.Res9patchStreamDecoder;
import jadx.core.utils.exceptions.JadxException;
......@@ -83,7 +82,7 @@ public final class ResourcesLoader {
return decodeStream(rf, (size, is) -> loadContent(jadxRef, rf, is));
} catch (JadxException e) {
LOG.error("Decode error", e);
CodeWriter cw = new CodeWriter();
ICodeWriter cw = jadxRef.getRoot().makeCodeWriter();
cw.add("Error decode ").add(rf.getType().toString().toLowerCase());
Utils.appendStackTrace(cw, e.getCause());
return ResContainer.textResource(rf.getDeobfName(), cw.finish());
......
package jadx.api.impl;
import java.util.Map;
import jadx.api.CodePosition;
import jadx.api.ICodeInfo;
public class AnnotatedCodeInfo implements ICodeInfo {
private final String code;
private final Map<Integer, Integer> lineMapping;
private final Map<CodePosition, Object> annotations;
public AnnotatedCodeInfo(ICodeInfo codeInfo) {
this(codeInfo.getCodeStr(), codeInfo.getLineMapping(), codeInfo.getAnnotations());
}
public AnnotatedCodeInfo(String code, Map<Integer, Integer> lineMapping, Map<CodePosition, Object> annotations) {
this.code = code;
this.lineMapping = lineMapping;
this.annotations = annotations;
}
@Override
public String getCodeStr() {
return code;
}
@Override
public Map<Integer, Integer> getLineMapping() {
return lineMapping;
}
@Override
public Map<CodePosition, Object> getAnnotations() {
return annotations;
}
@Override
public String toString() {
return code;
}
}
package jadx.core.codegen;
package jadx.api.impl;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.CodePosition;
import jadx.api.ICodeInfo;
import jadx.api.impl.SimpleCodeInfo;
import jadx.api.ICodeWriter;
import jadx.api.JadxArgs;
import jadx.core.dex.attributes.nodes.LineAttrNode;
import jadx.core.utils.StringUtils;
import jadx.core.utils.Utils;
public class CodeWriter {
private static final Logger LOG = LoggerFactory.getLogger(CodeWriter.class);
public static final String NL = System.getProperty("line.separator");
public static final String INDENT_STR = " ";
private static final boolean ADD_LINE_NUMBERS = false;
private static final String[] INDENT_CACHE = {
"",
INDENT_STR,
INDENT_STR + INDENT_STR,
INDENT_STR + INDENT_STR + INDENT_STR,
INDENT_STR + INDENT_STR + INDENT_STR + INDENT_STR,
INDENT_STR + INDENT_STR + INDENT_STR + INDENT_STR + INDENT_STR,
};
private StringBuilder buf;
@Nullable
private String code;
private String indentStr;
private int indent;
public class AnnotatedCodeWriter extends SimpleCodeWriter implements ICodeWriter {
private int line = 1;
private int offset = 0;
private int offset;
private Map<CodePosition, Object> annotations = Collections.emptyMap();
private Map<Integer, Integer> lineMap = Collections.emptyMap();
public CodeWriter() {
this.buf = new StringBuilder();
this.indent = 0;
this.indentStr = "";
if (ADD_LINE_NUMBERS) {
incIndent(3);
add(indentStr);
}
}
public CodeWriter startLine() {
addLine();
addLineIndent();
return this;
}
public CodeWriter startLine(char c) {
addLine();
addLineIndent();
add(c);
return this;
public AnnotatedCodeWriter() {
}
public CodeWriter startLine(String str) {
addLine();
addLineIndent();
add(str);
return this;
public AnnotatedCodeWriter(JadxArgs args) {
super(args);
}
public CodeWriter startLineWithNum(int sourceLine) {
if (sourceLine == 0) {
startLine();
return this;
}
if (ADD_LINE_NUMBERS) {
newLine();
attachSourceLine(sourceLine);
String ln = "/* " + sourceLine + " */ ";
add(ln);
if (indentStr.length() > ln.length()) {
add(indentStr.substring(ln.length()));
}
} else {
startLine();
attachSourceLine(sourceLine);
}
return this;
@Override
public boolean isMetadataSupported() {
return true;
}
public CodeWriter addMultiLine(String str) {
@Override
public AnnotatedCodeWriter addMultiLine(String str) {
if (str.contains(NL)) {
buf.append(str.replace(NL, NL + indentStr));
line += StringUtils.countMatches(str, NL);
......@@ -105,19 +43,27 @@ public class CodeWriter {
return this;
}
public CodeWriter add(String str) {
@Override
public AnnotatedCodeWriter add(String str) {
buf.append(str);
offset += str.length();
return this;
}
public CodeWriter add(char c) {
@Override
public AnnotatedCodeWriter add(char c) {
buf.append(c);
offset++;
return this;
}
CodeWriter add(CodeWriter code) {
@Override
public ICodeWriter add(ICodeWriter cw) {
if ((!(cw instanceof AnnotatedCodeWriter))) {
buf.append(cw.getCodeStr());
return this;
}
AnnotatedCodeWriter code = ((AnnotatedCodeWriter) cw);
line--;
for (Map.Entry<CodePosition, Object> entry : code.annotations.entrySet()) {
Object val = entry.getValue();
......@@ -126,7 +72,7 @@ public class CodeWriter {
node.setDefPosition(node.getDefPosition() + this.buf.length());
}
CodePosition pos = entry.getKey();
int usagePos = pos.getUsagePosition() + bufLength();
int usagePos = pos.getUsagePosition() + getLength();
attachAnnotation(val,
new CodePosition(line + pos.getLine(), pos.getOffset())
.setUsagePosition(usagePos));
......@@ -140,73 +86,26 @@ public class CodeWriter {
return this;
}
public CodeWriter newLine() {
addLine();
return this;
}
public CodeWriter addIndent() {
add(INDENT_STR);
return this;
}
private void addLine() {
@Override
protected void addLine() {
buf.append(NL);
line++;
offset = 0;
}
private CodeWriter addLineIndent() {
@Override
protected AnnotatedCodeWriter addLineIndent() {
buf.append(indentStr);
offset += indentStr.length();
return this;
}
private void updateIndent() {
int curIndent = indent;
if (curIndent < INDENT_CACHE.length) {
this.indentStr = INDENT_CACHE[curIndent];
} else {
this.indentStr = Utils.strRepeat(INDENT_STR, curIndent);
}
}
public void incIndent() {
incIndent(1);
}
public void decIndent() {
decIndent(1);
}
public void incIndent(int c) {
this.indent += c;
updateIndent();
}
public void decIndent(int c) {
this.indent -= c;
if (this.indent < 0) {
LOG.warn("Indent < 0");
this.indent = 0;
}
updateIndent();
}
public int getIndent() {
return indent;
}
public void setIndent(int indent) {
this.indent = indent;
updateIndent();
}
@Override
public int getLine() {
return line;
}
private static class DefinitionWrapper {
private static final class DefinitionWrapper {
private final LineAttrNode node;
private DefinitionWrapper(LineAttrNode node) {
......@@ -218,28 +117,31 @@ public class CodeWriter {
}
}
@Override
public void attachDefinition(LineAttrNode obj) {
obj.setDefPosition(buf.length());
attachAnnotation(obj);
attachAnnotation(new DefinitionWrapper(obj), new CodePosition(line, offset));
}
@Override
public void attachAnnotation(Object obj) {
attachAnnotation(obj,
new CodePosition(line, offset + 1).setUsagePosition(bufLength()));
attachAnnotation(obj, new CodePosition(line, offset + 1).setUsagePosition(getLength()));
}
@Override
public void attachLineAnnotation(Object obj) {
attachAnnotation(obj, new CodePosition(line, 0));
}
private Object attachAnnotation(Object obj, CodePosition pos) {
private void attachAnnotation(Object obj, CodePosition pos) {
if (annotations.isEmpty()) {
annotations = new HashMap<>();
}
return annotations.put(pos, obj);
annotations.put(pos, obj);
}
@Override
public void attachSourceLine(int sourceLine) {
if (sourceLine == 0) {
return;
......@@ -254,19 +156,13 @@ public class CodeWriter {
lineMap.put(decompiledLine, sourceLine);
}
@Override
public ICodeInfo finish() {
removeFirstEmptyLine();
processDefinitionAnnotations();
code = buf.toString();
String code = buf.toString();
buf = null;
return new SimpleCodeInfo(code, lineMap, annotations);
}
private void removeFirstEmptyLine() {
int len = NL.length();
if (buf.length() > len && buf.substring(0, len).equals(NL)) {
buf.delete(0, len);
}
return new AnnotatedCodeInfo(code, lineMap, annotations);
}
private void processDefinitionAnnotations() {
......@@ -282,20 +178,4 @@ public class CodeWriter {
});
}
}
public int bufLength() {
return buf.length();
}
public String getCodeStr() {
if (code == null) {
finish();
}
return code;
}
@Override
public String toString() {
return code != null ? code : buf.toString();
}
}
......@@ -9,21 +9,9 @@ import jadx.api.ICodeInfo;
public class SimpleCodeInfo implements ICodeInfo {
private final String code;
private final Map<Integer, Integer> lineMapping;
private final Map<CodePosition, Object> annotations;
public SimpleCodeInfo(String code) {
this(code, Collections.emptyMap(), Collections.emptyMap());
}
public SimpleCodeInfo(ICodeInfo codeInfo) {
this(codeInfo.getCodeStr(), codeInfo.getLineMapping(), codeInfo.getAnnotations());
}
public SimpleCodeInfo(String code, Map<Integer, Integer> lineMapping, Map<CodePosition, Object> annotations) {
this.code = code;
this.lineMapping = lineMapping;
this.annotations = annotations;
}
@Override
......@@ -33,12 +21,12 @@ public class SimpleCodeInfo implements ICodeInfo {
@Override
public Map<Integer, Integer> getLineMapping() {
return lineMapping;
return Collections.emptyMap();
}
@Override
public Map<CodePosition, Object> getAnnotations() {
return annotations;
return Collections.emptyMap();
}
@Override
......
package jadx.api.impl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.ICodeInfo;
import jadx.api.ICodeWriter;
import jadx.api.JadxArgs;
import jadx.core.dex.attributes.nodes.LineAttrNode;
import jadx.core.utils.Utils;
/**
* CodeWriter implementation without meta information support (only strings builder)
*/
public class SimpleCodeWriter implements ICodeWriter {
private static final Logger LOG = LoggerFactory.getLogger(SimpleCodeWriter.class);
private static final String[] INDENT_CACHE = {
"",
INDENT_STR,
INDENT_STR + INDENT_STR,
INDENT_STR + INDENT_STR + INDENT_STR,
INDENT_STR + INDENT_STR + INDENT_STR + INDENT_STR,
INDENT_STR + INDENT_STR + INDENT_STR + INDENT_STR + INDENT_STR,
};
protected StringBuilder buf = new StringBuilder();
protected String indentStr = "";
protected int indent = 0;
private final boolean insertLineNumbers;
public SimpleCodeWriter() {
this.insertLineNumbers = false;
}
public SimpleCodeWriter(JadxArgs args) {
this.insertLineNumbers = args.isInsertDebugLines();
if (insertLineNumbers) {
incIndent(3);
add(indentStr);
}
}
@Override
public boolean isMetadataSupported() {
return false;
}
@Override
public SimpleCodeWriter startLine() {
addLine();
addLineIndent();
return this;
}
@Override
public SimpleCodeWriter startLine(char c) {
startLine();
add(c);
return this;
}
@Override
public SimpleCodeWriter startLine(String str) {
startLine();
add(str);
return this;
}
@Override
public SimpleCodeWriter startLineWithNum(int sourceLine) {
if (sourceLine == 0) {
startLine();
return this;
}
if (this.insertLineNumbers) {
newLine();
attachSourceLine(sourceLine);
int start = getLength();
add("/* ").add(Integer.toString(sourceLine)).add(" */ ");
int len = getLength() - start;
if (indentStr.length() > len) {
add(indentStr.substring(len));
}
} else {
startLine();
attachSourceLine(sourceLine);
}
return this;
}
@Override
public SimpleCodeWriter addMultiLine(String str) {
if (str.contains(NL)) {
buf.append(str.replace(NL, NL + indentStr));
} else {
buf.append(str);
}
return this;
}
@Override
public SimpleCodeWriter add(String str) {
buf.append(str);
return this;
}
@Override
public SimpleCodeWriter add(char c) {
buf.append(c);
return this;
}
@Override
public ICodeWriter add(ICodeWriter cw) {
buf.append(cw.getCodeStr());
return this;
}
@Override
public SimpleCodeWriter newLine() {
addLine();
return this;
}
@Override
public SimpleCodeWriter addIndent() {
add(INDENT_STR);
return this;
}
protected void addLine() {
buf.append(NL);
}
protected SimpleCodeWriter addLineIndent() {
buf.append(indentStr);
return this;
}
private void updateIndent() {
int curIndent = indent;
if (curIndent < INDENT_CACHE.length) {
this.indentStr = INDENT_CACHE[curIndent];
} else {
this.indentStr = Utils.strRepeat(INDENT_STR, curIndent);
}
}
@Override
public void incIndent() {
incIndent(1);
}
@Override
public void decIndent() {
decIndent(1);
}
private void incIndent(int c) {
this.indent += c;
updateIndent();
}
private void decIndent(int c) {
this.indent -= c;
if (this.indent < 0) {
LOG.warn("Indent < 0");
this.indent = 0;
}
updateIndent();
}
@Override
public int getIndent() {
return indent;
}
@Override
public void setIndent(int indent) {
this.indent = indent;
updateIndent();
}
@Override
public int getLine() {
return 0;
}
@Override
public void attachDefinition(LineAttrNode obj) {
// no op
}
@Override
public void attachAnnotation(Object obj) {
// no op
}
@Override
public void attachLineAnnotation(Object obj) {
// no op
}
@Override
public void attachSourceLine(int sourceLine) {
// no op
}
@Override
public ICodeInfo finish() {
removeFirstEmptyLine();
String code = buf.toString();
buf = null;
return new SimpleCodeInfo(code);
}
protected void removeFirstEmptyLine() {
int len = NL.length();
if (buf.length() > len && buf.substring(0, len).equals(NL)) {
buf.delete(0, len);
}
}
@Override
public int getLength() {
return buf.length();
}
@Override
public String getCodeStr() {
removeFirstEmptyLine();
return buf.toString();
}
@Override
public String toString() {
return getCodeStr();
}
}
......@@ -7,6 +7,7 @@ import java.util.Map.Entry;
import org.jetbrains.annotations.Nullable;
import jadx.api.ICodeWriter;
import jadx.api.plugins.input.data.IFieldData;
import jadx.api.plugins.input.data.annotations.EncodedValue;
import jadx.api.plugins.input.data.annotations.IAnnotation;
......@@ -34,19 +35,19 @@ public class AnnotationGen {
this.classGen = classGen;
}
public void addForClass(CodeWriter code) {
public void addForClass(ICodeWriter code) {
add(cls, code);
}
public void addForMethod(CodeWriter code, MethodNode mth) {
public void addForMethod(ICodeWriter code, MethodNode mth) {
add(mth, code);
}
public void addForField(CodeWriter code, FieldNode field) {
public void addForField(ICodeWriter code, FieldNode field) {
add(field, code);
}
public void addForParameter(CodeWriter code, MethodParameters paramsAnnotations, int n) {
public void addForParameter(ICodeWriter code, MethodParameters paramsAnnotations, int n) {
List<AnnotationsList> paramList = paramsAnnotations.getParamList();
if (n >= paramList.size()) {
return;
......@@ -61,7 +62,7 @@ public class AnnotationGen {
}
}
private void add(IAttributeNode node, CodeWriter code) {
private void add(IAttributeNode node, ICodeWriter code) {
AnnotationsList aList = node.get(AType.ANNOTATION_LIST);
if (aList == null || aList.isEmpty()) {
return;
......@@ -75,7 +76,7 @@ public class AnnotationGen {
}
}
private void formatAnnotation(CodeWriter code, IAnnotation a) {
private void formatAnnotation(ICodeWriter code, IAnnotation a) {
code.add('@');
ClassNode annCls = cls.root().resolveClass(a.getAnnotationClass());
if (annCls != null) {
......@@ -116,7 +117,7 @@ public class AnnotationGen {
return paramName;
}
public void addThrows(MethodNode mth, CodeWriter code) {
public void addThrows(MethodNode mth, ICodeWriter code) {
List<ArgType> throwList = mth.getThrows();
if (!throwList.isEmpty()) {
code.add(" throws ");
......@@ -143,7 +144,7 @@ public class AnnotationGen {
}
// TODO: refactor this boilerplate code
public void encodeValue(RootNode root, CodeWriter code, EncodedValue encodedValue) {
public void encodeValue(RootNode root, ICodeWriter code, EncodedValue encodedValue) {
if (encodedValue == null) {
code.add("null");
return;
......
......@@ -14,6 +14,7 @@ import java.util.stream.Stream;
import org.jetbrains.annotations.Nullable;
import jadx.api.ICodeInfo;
import jadx.api.ICodeWriter;
import jadx.api.JadxArgs;
import jadx.api.plugins.input.data.AccessFlags;
import jadx.api.plugins.input.data.annotations.EncodedType;
......@@ -54,7 +55,7 @@ public class ClassGen {
private final boolean showInconsistentCode;
private final Set<ClassInfo> imports = new HashSet<>();
private int clsDeclLine;
private int clsDeclOffset;
private boolean bodyGenStarted;
......@@ -81,10 +82,10 @@ public class ClassGen {
}
public ICodeInfo makeClass() throws CodegenException {
CodeWriter clsBody = new CodeWriter();
ICodeWriter clsBody = cls.root().makeCodeWriter();
addClassCode(clsBody);
CodeWriter clsCode = new CodeWriter();
ICodeWriter clsCode = cls.root().makeCodeWriter();
if (!"".equals(cls.getPackage())) {
clsCode.add("package ").add(cls.getPackage()).add(';');
clsCode.newLine();
......@@ -109,7 +110,7 @@ public class ClassGen {
return clsCode.finish();
}
public void addClassCode(CodeWriter code) throws CodegenException {
public void addClassCode(ICodeWriter code) throws CodegenException {
if (cls.contains(AFlag.DONT_GENERATE)) {
return;
}
......@@ -122,7 +123,7 @@ public class ClassGen {
addClassBody(code);
}
public void addClassDeclaration(CodeWriter clsCode) {
public void addClassDeclaration(ICodeWriter clsCode) {
AccessInfo af = cls.getAccessFlags();
if (af.isInterface()) {
af = af.remove(AccessFlags.ABSTRACT)
......@@ -141,8 +142,7 @@ public class ClassGen {
annotationGen.addForClass(clsCode);
insertRenameInfo(clsCode, cls);
CodeGenUtils.addSourceFileInfo(clsCode, cls);
clsCode.startLineWithNum(cls.getSourceLine());
clsCode.add(af.makeString());
clsCode.startLineWithNum(cls.getSourceLine()).add(af.makeString());
if (af.isInterface()) {
if (af.isAnnotation()) {
clsCode.add('@');
......@@ -187,7 +187,7 @@ public class ClassGen {
}
}
public boolean addGenericTypeParameters(CodeWriter code, List<ArgType> generics, boolean classDeclaration) {
public boolean addGenericTypeParameters(ICodeWriter code, List<ArgType> generics, boolean classDeclaration) {
if (generics == null || generics.isEmpty()) {
return false;
}
......@@ -228,7 +228,7 @@ public class ClassGen {
return true;
}
public void addClassBody(CodeWriter clsCode) throws CodegenException {
public void addClassBody(ICodeWriter clsCode) throws CodegenException {
addClassBody(clsCode, false);
}
......@@ -236,10 +236,10 @@ public class ClassGen {
* @param printClassName allows to print the original class name as comment (e.g. for inlined
* classes)
*/
public void addClassBody(CodeWriter clsCode, boolean printClassName) throws CodegenException {
public void addClassBody(ICodeWriter clsCode, boolean printClassName) throws CodegenException {
clsCode.add('{');
setBodyGenStarted(true);
clsDeclLine = clsCode.getLine();
clsDeclOffset = clsCode.getLength();
clsCode.incIndent();
if (printClassName) {
clsCode.startLine();
......@@ -251,7 +251,7 @@ public class ClassGen {
clsCode.startLine('}');
}
private void addInnerClsAndMethods(CodeWriter clsCode) {
private void addInnerClsAndMethods(ICodeWriter clsCode) {
Stream.of(cls.getInnerClasses(), cls.getMethods())
.flatMap(Collection::stream)
.filter(node -> !node.contains(AFlag.DONT_GENERATE) || fallback)
......@@ -265,7 +265,7 @@ public class ClassGen {
});
}
private void addInnerClass(CodeWriter code, ClassNode innerCls) {
private void addInnerClass(ICodeWriter code, ClassNode innerCls) {
try {
ClassGen inClGen = new ClassGen(innerCls, getParentGen());
code.newLine();
......@@ -285,8 +285,8 @@ public class ClassGen {
return false;
}
private void addMethod(CodeWriter code, MethodNode mth) {
if (code.getLine() != clsDeclLine) {
private void addMethod(ICodeWriter code, MethodNode mth) {
if (code.getLength() != clsDeclOffset) {
code.newLine();
}
int savedIndent = code.getIndent();
......@@ -314,7 +314,7 @@ public class ClassGen {
return false;
}
public void addMethodCode(CodeWriter code, MethodNode mth) throws CodegenException {
public void addMethodCode(ICodeWriter code, MethodNode mth) throws CodegenException {
CodeGenUtils.addComments(code, mth);
if (mth.isNoCode()) {
MethodGen mthGen = new MethodGen(this, mth);
......@@ -344,7 +344,7 @@ public class ClassGen {
}
}
public void insertDecompilationProblems(CodeWriter code, AttrNode node) {
public void insertDecompilationProblems(ICodeWriter code, AttrNode node) {
List<JadxError> errors = node.getAll(AType.JADX_ERROR);
if (!errors.isEmpty()) {
errors.stream().distinct().sorted().forEach(err -> {
......@@ -365,14 +365,14 @@ public class ClassGen {
}
}
private void addFields(CodeWriter code) throws CodegenException {
private void addFields(ICodeWriter code) throws CodegenException {
addEnumFields(code);
for (FieldNode f : cls.getFields()) {
addField(code, f);
}
}
public void addField(CodeWriter code, FieldNode f) {
public void addField(ICodeWriter code, FieldNode f) {
if (f.contains(AFlag.DONT_GENERATE)) {
return;
}
......@@ -418,7 +418,7 @@ public class ClassGen {
return false;
}
private void addEnumFields(CodeWriter code) throws CodegenException {
private void addEnumFields(ICodeWriter code) throws CodegenException {
EnumClassAttr enumFields = cls.get(AType.ENUM_CLASS);
if (enumFields == null) {
return;
......@@ -470,7 +470,7 @@ public class ClassGen {
return new InsnGen(mthGen, false);
}
private void addInsnBody(InsnGen insnGen, CodeWriter code, InsnNode insn) {
private void addInsnBody(InsnGen insnGen, ICodeWriter code, InsnNode insn) {
try {
insnGen.makeInsn(insn, code, InsnGen.Flags.BODY_ONLY_NOWRAP);
} catch (Exception e) {
......@@ -478,7 +478,7 @@ public class ClassGen {
}
}
public void useType(CodeWriter code, ArgType type) {
public void useType(ICodeWriter code, ArgType type) {
PrimitiveType stype = type.getPrimitiveType();
if (stype == null) {
code.add(type.toString());
......@@ -496,11 +496,11 @@ public class ClassGen {
}
}
public void useClass(CodeWriter code, String rawCls) {
public void useClass(ICodeWriter code, String rawCls) {
useClass(code, ArgType.object(rawCls));
}
public void useClass(CodeWriter code, ArgType type) {
public void useClass(ICodeWriter code, ArgType type) {
ArgType outerType = type.getOuterType();
if (outerType != null) {
useClass(code, outerType);
......@@ -535,7 +535,7 @@ public class ClassGen {
}
}
private void useClassShortName(CodeWriter code, String object) {
private void useClassShortName(ICodeWriter code, String object) {
ClassInfo classInfo = ClassInfo.fromName(cls.root(), object);
ClassNode classNode = cls.root().resolveClass(classInfo);
if (classNode != null) {
......@@ -544,7 +544,7 @@ public class ClassGen {
code.add(classInfo.getAliasShortName());
}
public void useClass(CodeWriter code, ClassInfo classInfo) {
public void useClass(ICodeWriter code, ClassInfo classInfo) {
ClassNode classNode = cls.root().resolveClass(classInfo);
if (classNode != null) {
useClass(code, classNode);
......@@ -553,12 +553,12 @@ public class ClassGen {
}
}
public void useClass(CodeWriter code, ClassNode classNode) {
public void useClass(ICodeWriter code, ClassNode classNode) {
code.attachAnnotation(classNode);
addClsName(code, classNode.getClassInfo());
}
private void addClsName(CodeWriter code, ClassInfo classInfo) {
private void addClsName(ICodeWriter code, ClassInfo classInfo) {
String clsName = useClassInternal(cls.getClassInfo(), classInfo);
code.add(clsName);
}
......@@ -684,14 +684,14 @@ public class ClassGen {
return searchCollision(root, useCls.getParentClass(), searchCls);
}
private void insertRenameInfo(CodeWriter code, ClassNode cls) {
private void insertRenameInfo(ICodeWriter code, ClassNode cls) {
ClassInfo classInfo = cls.getClassInfo();
if (classInfo.hasAlias()) {
CodeGenUtils.addRenamedComment(code, cls, classInfo.getType().getObject());
}
}
private static void addClassUsageInfo(CodeWriter code, ClassNode cls) {
private static void addClassUsageInfo(ICodeWriter code, ClassNode cls) {
List<ClassNode> deps = cls.getDependencies();
code.startLine("// deps - ").add(Integer.toString(deps.size()));
for (ClassNode depCls : deps) {
......@@ -709,7 +709,7 @@ public class ClassGen {
}
}
static void addMthUsageInfo(CodeWriter code, MethodNode mth) {
static void addMthUsageInfo(ICodeWriter code, MethodNode mth) {
List<MethodNode> useInMths = mth.getUseIn();
code.startLine("// use in methods - ").add(Integer.toString(useInMths.size()));
for (MethodNode useMth : useInMths) {
......@@ -717,7 +717,7 @@ public class ClassGen {
}
}
private static void addFieldUsageInfo(CodeWriter code, FieldNode fieldNode) {
private static void addFieldUsageInfo(ICodeWriter code, FieldNode fieldNode) {
List<MethodNode> useInMths = fieldNode.getUseIn();
code.startLine("// use in methods - ").add(Integer.toString(useInMths.size()));
for (MethodNode useMth : useInMths) {
......
......@@ -4,6 +4,7 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import jadx.api.ICodeWriter;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.instructions.ArithNode;
import jadx.core.dex.instructions.IfOp;
......@@ -41,15 +42,15 @@ public class ConditionGen extends InsnGen {
super(insnGen.mgen, insnGen.fallback);
}
void add(CodeWriter code, IfCondition condition) throws CodegenException {
void add(ICodeWriter code, IfCondition condition) throws CodegenException {
add(code, new CondStack(), condition);
}
void wrap(CodeWriter code, IfCondition condition) throws CodegenException {
void wrap(ICodeWriter code, IfCondition condition) throws CodegenException {
wrap(code, new CondStack(), condition);
}
private void add(CodeWriter code, CondStack stack, IfCondition condition) throws CodegenException {
private void add(ICodeWriter code, CondStack stack, IfCondition condition) throws CodegenException {
stack.push(condition);
switch (condition.getMode()) {
case COMPARE:
......@@ -75,7 +76,7 @@ public class ConditionGen extends InsnGen {
stack.pop();
}
private void wrap(CodeWriter code, CondStack stack, IfCondition cond) throws CodegenException {
private void wrap(ICodeWriter code, CondStack stack, IfCondition cond) throws CodegenException {
boolean wrap = isWrapNeeded(cond);
if (wrap) {
code.add('(');
......@@ -86,7 +87,7 @@ public class ConditionGen extends InsnGen {
}
}
private void wrap(CodeWriter code, InsnArg firstArg) throws CodegenException {
private void wrap(ICodeWriter code, InsnArg firstArg) throws CodegenException {
boolean wrap = isArgWrapNeeded(firstArg);
if (wrap) {
code.add('(');
......@@ -97,7 +98,7 @@ public class ConditionGen extends InsnGen {
}
}
private void addCompare(CodeWriter code, CondStack stack, Compare compare) throws CodegenException {
private void addCompare(ICodeWriter code, CondStack stack, Compare compare) throws CodegenException {
IfOp op = compare.getOp();
InsnArg firstArg = compare.getA();
InsnArg secondArg = compare.getB();
......@@ -130,7 +131,7 @@ public class ConditionGen extends InsnGen {
addArg(code, secondArg, isArgWrapNeeded(secondArg));
}
private void addTernary(CodeWriter code, CondStack stack, IfCondition condition) throws CodegenException {
private void addTernary(ICodeWriter code, CondStack stack, IfCondition condition) throws CodegenException {
add(code, stack, condition.first());
code.add(" ? ");
add(code, stack, condition.second());
......@@ -138,12 +139,12 @@ public class ConditionGen extends InsnGen {
add(code, stack, condition.third());
}
private void addNot(CodeWriter code, CondStack stack, IfCondition condition) throws CodegenException {
private void addNot(ICodeWriter code, CondStack stack, IfCondition condition) throws CodegenException {
code.add('!');
wrap(code, stack, condition.getArgs().get(0));
}
private void addAndOr(CodeWriter code, CondStack stack, IfCondition condition) throws CodegenException {
private void addAndOr(ICodeWriter code, CondStack stack, IfCondition condition) throws CodegenException {
String mode = condition.getMode() == Mode.AND ? " && " : " || ";
Iterator<IfCondition> it = condition.getArgs().iterator();
while (it.hasNext()) {
......
......@@ -9,6 +9,7 @@ import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.ICodeWriter;
import jadx.api.plugins.input.data.MethodHandleType;
import jadx.core.deobf.NameMapper;
import jadx.core.dex.attributes.AFlag;
......@@ -88,19 +89,19 @@ public class InsnGen {
return fallback;
}
public void addArgDot(CodeWriter code, InsnArg arg) throws CodegenException {
int len = code.bufLength();
public void addArgDot(ICodeWriter code, InsnArg arg) throws CodegenException {
int len = code.getLength();
addArg(code, arg, true);
if (len != code.bufLength()) {
if (len != code.getLength()) {
code.add('.');
}
}
public void addArg(CodeWriter code, InsnArg arg) throws CodegenException {
public void addArg(ICodeWriter code, InsnArg arg) throws CodegenException {
addArg(code, arg, true);
}
public void addArg(CodeWriter code, InsnArg arg, boolean wrap) throws CodegenException {
public void addArg(ICodeWriter code, InsnArg arg, boolean wrap) throws CodegenException {
if (arg.isRegister()) {
CodeVar codeVar = CodeGenUtils.getCodeVar((RegisterArg) arg);
if (codeVar != null) {
......@@ -127,7 +128,7 @@ public class InsnGen {
}
}
private void addWrappedArg(CodeWriter code, InsnWrapArg arg, boolean wrap) throws CodegenException {
private void addWrappedArg(ICodeWriter code, InsnWrapArg arg, boolean wrap) throws CodegenException {
InsnNode wrapInsn = arg.getWrapInsn();
if (wrapInsn.contains(AFlag.FORCE_ASSIGN_INLINE)) {
code.add('(');
......@@ -139,7 +140,7 @@ public class InsnGen {
}
}
public void assignVar(CodeWriter code, InsnNode insn) throws CodegenException {
public void assignVar(ICodeWriter code, InsnNode insn) throws CodegenException {
RegisterArg arg = insn.getResult();
if (insn.contains(AFlag.DECLARE_VAR)) {
declareVar(code, arg);
......@@ -148,11 +149,11 @@ public class InsnGen {
}
}
public void declareVar(CodeWriter code, RegisterArg arg) {
public void declareVar(ICodeWriter code, RegisterArg arg) {
declareVar(code, arg.getSVar().getCodeVar());
}
public void declareVar(CodeWriter code, CodeVar codeVar) {
public void declareVar(ICodeWriter code, CodeVar codeVar) {
if (codeVar.isFinal()) {
code.add("final ");
}
......@@ -174,7 +175,7 @@ public class InsnGen {
return TypeGen.literalToString(arg, mth, fallback);
}
private void instanceField(CodeWriter code, FieldInfo field, InsnArg arg) throws CodegenException {
private void instanceField(ICodeWriter code, FieldInfo field, InsnArg arg) throws CodegenException {
ClassNode pCls = mth.getParentClass();
FieldNode fieldNode = pCls.root().deepResolveField(field);
if (fieldNode != null) {
......@@ -203,7 +204,7 @@ public class InsnGen {
}
}
public static void makeStaticFieldAccess(CodeWriter code, FieldInfo field, ClassGen clsGen) {
public static void makeStaticFieldAccess(ICodeWriter code, FieldInfo field, ClassGen clsGen) {
ClassInfo declClass = field.getDeclClass();
// TODO
boolean fieldFromThisClass = clsGen.getClassNode().getClassInfo().equals(declClass);
......@@ -225,23 +226,23 @@ public class InsnGen {
}
}
protected void staticField(CodeWriter code, FieldInfo field) {
protected void staticField(ICodeWriter code, FieldInfo field) {
makeStaticFieldAccess(code, field, mgen.getClassGen());
}
public void useClass(CodeWriter code, ArgType type) {
public void useClass(ICodeWriter code, ArgType type) {
mgen.getClassGen().useClass(code, type);
}
public void useClass(CodeWriter code, ClassInfo cls) {
public void useClass(ICodeWriter code, ClassInfo cls) {
mgen.getClassGen().useClass(code, cls);
}
protected void useType(CodeWriter code, ArgType type) {
protected void useType(ICodeWriter code, ArgType type) {
mgen.getClassGen().useType(code, type);
}
public void makeInsn(InsnNode insn, CodeWriter code) throws CodegenException {
public void makeInsn(InsnNode insn, ICodeWriter code) throws CodegenException {
makeInsn(insn, code, null);
}
......@@ -249,7 +250,7 @@ public class InsnGen {
private static final Set<Flags> BODY_ONLY_FLAG = EnumSet.of(Flags.BODY_ONLY);
private static final Set<Flags> BODY_ONLY_NOWRAP_FLAGS = EnumSet.of(Flags.BODY_ONLY_NOWRAP);
protected void makeInsn(InsnNode insn, CodeWriter code, Flags flag) throws CodegenException {
protected void makeInsn(InsnNode insn, ICodeWriter code, Flags flag) throws CodegenException {
if (insn.getType() == InsnType.REGION_ARG) {
return;
}
......@@ -284,7 +285,7 @@ public class InsnGen {
}
}
private void makeInsnBody(CodeWriter code, InsnNode insn, Set<Flags> state) throws CodegenException {
private void makeInsnBody(ICodeWriter code, InsnNode insn, Set<Flags> state) throws CodegenException {
switch (insn.getType()) {
case CONST_STR:
String str = ((ConstStringNode) insn).getString();
......@@ -590,7 +591,7 @@ public class InsnGen {
* In most cases must be combined with new array instructions.
* Use one by one array fill (can be replaced with System.arrayCopy)
*/
private void fillArray(CodeWriter code, FillArrayInsn arrayNode) throws CodegenException {
private void fillArray(ICodeWriter code, FillArrayInsn arrayNode) throws CodegenException {
code.add("// fill-array-data instruction");
code.startLine();
InsnArg arrArg = arrayNode.getArg(0);
......@@ -614,7 +615,7 @@ public class InsnGen {
}
}
private void oneArgInsn(CodeWriter code, InsnNode insn, Set<Flags> state, char op) throws CodegenException {
private void oneArgInsn(ICodeWriter code, InsnNode insn, Set<Flags> state, char op) throws CodegenException {
boolean wrap = state.contains(Flags.BODY_ONLY);
if (wrap) {
code.add('(');
......@@ -636,7 +637,7 @@ public class InsnGen {
}
}
private void filledNewArray(FilledNewArrayNode insn, CodeWriter code) throws CodegenException {
private void filledNewArray(FilledNewArrayNode insn, ICodeWriter code) throws CodegenException {
if (!insn.contains(AFlag.DECLARE_VAR)) {
code.add("new ");
useType(code, insn.getArrayType());
......@@ -652,7 +653,7 @@ public class InsnGen {
code.add('}');
}
private void makeConstructor(ConstructorInsn insn, CodeWriter code) throws CodegenException {
private void makeConstructor(ConstructorInsn insn, ICodeWriter code) throws CodegenException {
ClassNode cls = mth.root().resolveClass(insn.getClassType());
if (cls != null && cls.isAnonymous() && !fallback) {
cls.ensureProcessed();
......@@ -691,7 +692,7 @@ public class InsnGen {
generateMethodArguments(code, insn, 0, callMth);
}
private void inlineAnonymousConstructor(CodeWriter code, ClassNode cls, ConstructorInsn insn) throws CodegenException {
private void inlineAnonymousConstructor(ICodeWriter code, ClassNode cls, ConstructorInsn insn) throws CodegenException {
if (this.mth.getParentClass() == cls) {
cls.remove(AFlag.ANONYMOUS_CLASS);
cls.remove(AFlag.DONT_GENERATE);
......@@ -727,7 +728,7 @@ public class InsnGen {
new ClassGen(cls, mgen.getClassGen().getParentGen()).addClassBody(code, true);
}
private void makeInvoke(InvokeNode insn, CodeWriter code) throws CodegenException {
private void makeInvoke(InvokeNode insn, ICodeWriter code) throws CodegenException {
InvokeType type = insn.getInvokeType();
if (type == InvokeType.CUSTOM) {
makeInvokeLambda(code, (InvokeCustomNode) insn);
......@@ -778,7 +779,7 @@ public class InsnGen {
generateMethodArguments(code, insn, k, callMthNode);
}
private void makeInvokeLambda(CodeWriter code, InvokeCustomNode customNode) throws CodegenException {
private void makeInvokeLambda(ICodeWriter code, InvokeCustomNode customNode) throws CodegenException {
if (customNode.isUseRef()) {
makeRefLambda(code, customNode);
return;
......@@ -791,7 +792,7 @@ public class InsnGen {
makeInlinedLambdaMethod(code, customNode, callMth);
}
private void makeRefLambda(CodeWriter code, InvokeCustomNode customNode) {
private void makeRefLambda(ICodeWriter code, InvokeCustomNode customNode) {
InsnNode callInsn = customNode.getCallInsn();
if (callInsn instanceof ConstructorInsn) {
MethodInfo callMth = ((ConstructorInsn) callInsn).getCallMth();
......@@ -811,7 +812,7 @@ public class InsnGen {
}
}
private void makeSimpleLambda(CodeWriter code, InvokeCustomNode customNode) {
private void makeSimpleLambda(ICodeWriter code, InvokeCustomNode customNode) {
try {
InsnNode callInsn = customNode.getCallInsn();
MethodInfo implMthInfo = customNode.getImplMthInfo();
......@@ -858,7 +859,7 @@ public class InsnGen {
}
}
private void makeInlinedLambdaMethod(CodeWriter code, InvokeCustomNode customNode, MethodNode callMth) throws CodegenException {
private void makeInlinedLambdaMethod(ICodeWriter code, InvokeCustomNode customNode, MethodNode callMth) throws CodegenException {
MethodGen callMthGen = new MethodGen(mgen.getClassGen(), callMth);
NameGen nameGen = callMthGen.getNameGen();
nameGen.inheritUsedNames(this.mgen.getNameGen());
......@@ -894,7 +895,7 @@ public class InsnGen {
}
@Nullable
private ClassInfo getClassForSuperCall(CodeWriter code, MethodInfo callMth) {
private ClassInfo getClassForSuperCall(ICodeWriter code, MethodInfo callMth) {
ClassNode useCls = mth.getParentClass();
ClassInfo insnCls = useCls.getClassInfo();
ClassInfo declClass = callMth.getDeclClass();
......@@ -923,7 +924,7 @@ public class InsnGen {
return useCls.getParentClass().getClassInfo();
}
void generateMethodArguments(CodeWriter code, BaseInvokeNode insn, int startArgNum,
void generateMethodArguments(ICodeWriter code, BaseInvokeNode insn, int startArgNum,
@Nullable MethodNode mthNode) throws CodegenException {
int k = startArgNum;
if (mthNode != null && mthNode.contains(AFlag.SKIP_FIRST_ARG)) {
......@@ -960,7 +961,7 @@ public class InsnGen {
/**
* Expand varArgs from filled array.
*/
private boolean processVarArg(CodeWriter code, BaseInvokeNode invokeInsn, InsnArg lastArg) throws CodegenException {
private boolean processVarArg(ICodeWriter code, BaseInvokeNode invokeInsn, InsnArg lastArg) throws CodegenException {
if (!invokeInsn.contains(AFlag.VARARG_CALL)) {
return false;
}
......@@ -982,7 +983,7 @@ public class InsnGen {
return true;
}
private void makeTernary(TernaryInsn insn, CodeWriter code, Set<Flags> state) throws CodegenException {
private void makeTernary(TernaryInsn insn, ICodeWriter code, Set<Flags> state) throws CodegenException {
boolean wrap = state.contains(Flags.BODY_ONLY);
if (wrap) {
code.add('(');
......@@ -1005,7 +1006,7 @@ public class InsnGen {
}
}
private void addCastIfNeeded(CodeWriter code, InsnArg first, InsnArg second) {
private void addCastIfNeeded(ICodeWriter code, InsnArg first, InsnArg second) {
if (first.isLiteral() && second.isLiteral()) {
if (first.getType() == ArgType.BYTE) {
long lit1 = ((LiteralArg) first).getLiteral();
......@@ -1032,7 +1033,7 @@ public class InsnGen {
}
}
private void makeArith(ArithNode insn, CodeWriter code, Set<Flags> state) throws CodegenException {
private void makeArith(ArithNode insn, ICodeWriter code, Set<Flags> state) throws CodegenException {
if (insn.contains(AFlag.ARITH_ONEARG)) {
makeArithOneArg(insn, code);
return;
......@@ -1052,7 +1053,7 @@ public class InsnGen {
}
}
private void makeArithOneArg(ArithNode insn, CodeWriter code) throws CodegenException {
private void makeArithOneArg(ArithNode insn, ICodeWriter code) throws CodegenException {
ArithOp op = insn.getOp();
InsnArg resArg = insn.getArg(0);
InsnArg arg = insn.getArg(1);
......
......@@ -9,6 +9,7 @@ import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.ICodeWriter;
import jadx.api.plugins.input.data.AccessFlags;
import jadx.api.plugins.input.data.annotations.EncodedValue;
import jadx.core.Consts;
......@@ -72,7 +73,7 @@ public class MethodGen {
return mth;
}
public boolean addDefinition(CodeWriter code) {
public boolean addDefinition(ICodeWriter code) {
if (mth.getMethodInfo().isClassInit()) {
code.attachDefinition(mth);
code.startLine("static");
......@@ -162,7 +163,7 @@ public class MethodGen {
return true;
}
private void addOverrideAnnotation(CodeWriter code, MethodNode mth) {
private void addOverrideAnnotation(ICodeWriter code, MethodNode mth) {
MethodOverrideAttr overrideAttr = mth.get(AType.METHOD_OVERRIDE);
if (overrideAttr == null) {
return;
......@@ -178,7 +179,7 @@ public class MethodGen {
}
}
private void addMethodArguments(CodeWriter code, List<RegisterArg> args) {
private void addMethodArguments(ICodeWriter code, List<RegisterArg> args) {
MethodParameters paramsAnnotation = mth.get(AType.ANNOTATION_MTH_PARAMETERS);
int i = 0;
Iterator<RegisterArg> it = args.iterator();
......@@ -243,7 +244,7 @@ public class MethodGen {
}
}
public void addInstructions(CodeWriter code) throws CodegenException {
public void addInstructions(ICodeWriter code) throws CodegenException {
if (mth.root().getArgs().isFallbackMode()) {
addFallbackMethodCode(code, FALLBACK_MODE);
} else if (classGen.isFallbackMode()) {
......@@ -253,7 +254,7 @@ public class MethodGen {
}
}
public void addRegionInsns(CodeWriter code) throws CodegenException {
public void addRegionInsns(ICodeWriter code) throws CodegenException {
try {
RegionGen regionGen = new RegionGen(this);
regionGen.makeRegion(code, mth.getRegion());
......@@ -271,7 +272,7 @@ public class MethodGen {
}
}
public void dumpInstructions(CodeWriter code) {
public void dumpInstructions(ICodeWriter code) {
code.startLine("/*");
addFallbackMethodCode(code, COMMENTED_DUMP);
code.startLine("*/");
......@@ -287,7 +288,7 @@ public class MethodGen {
.add("\");");
}
public void addFallbackMethodCode(CodeWriter code, FallbackOption fallbackOption) {
public void addFallbackMethodCode(ICodeWriter code, FallbackOption fallbackOption) {
// load original instructions
try {
mth.unload();
......@@ -329,7 +330,7 @@ public class MethodGen {
COMMENTED_DUMP
}
public static void addFallbackInsns(CodeWriter code, MethodNode mth, InsnNode[] insnArr, FallbackOption option) {
public static void addFallbackInsns(ICodeWriter code, MethodNode mth, InsnNode[] insnArr, FallbackOption option) {
int startIndent = code.getIndent();
InsnGen insnGen = new InsnGen(getFallbackMethodGen(mth), true);
boolean attachInsns = mth.root().getArgs().isJsonOutput();
......
......@@ -8,6 +8,7 @@ import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.ICodeWriter;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.fldinit.FieldInitAttr;
......@@ -21,7 +22,13 @@ import jadx.core.dex.instructions.args.CodeVar;
import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.NamedArg;
import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.nodes.*;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.IBlock;
import jadx.core.dex.nodes.IContainer;
import jadx.core.dex.nodes.IRegion;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.VariableNode;
import jadx.core.dex.regions.Region;
import jadx.core.dex.regions.SwitchRegion;
import jadx.core.dex.regions.SwitchRegion.CaseInfo;
......@@ -40,7 +47,7 @@ import jadx.core.utils.RegionUtils;
import jadx.core.utils.exceptions.CodegenException;
import jadx.core.utils.exceptions.JadxRuntimeException;
import static jadx.core.dex.nodes.VariableNode.*;
import static jadx.core.dex.nodes.VariableNode.VarKind;
public class RegionGen extends InsnGen {
private static final Logger LOG = LoggerFactory.getLogger(RegionGen.class);
......@@ -49,7 +56,7 @@ public class RegionGen extends InsnGen {
super(mgen, false);
}
public void makeRegion(CodeWriter code, IContainer cont) throws CodegenException {
public void makeRegion(ICodeWriter code, IContainer cont) throws CodegenException {
if (cont instanceof IBlock) {
makeSimpleBlock((IBlock) cont, code);
} else if (cont instanceof IRegion) {
......@@ -74,7 +81,7 @@ public class RegionGen extends InsnGen {
}
}
private void declareVars(CodeWriter code, IContainer cont) {
private void declareVars(ICodeWriter code, IContainer cont) {
DeclareVariablesAttr declVars = cont.get(AType.DECLARE_VARIABLES);
if (declVars != null) {
for (CodeVar v : declVars.getVars()) {
......@@ -85,20 +92,20 @@ public class RegionGen extends InsnGen {
}
}
private void makeSimpleRegion(CodeWriter code, Region region) throws CodegenException {
private void makeSimpleRegion(ICodeWriter code, Region region) throws CodegenException {
declareVars(code, region);
for (IContainer c : region.getSubBlocks()) {
makeRegion(code, c);
}
}
public void makeRegionIndent(CodeWriter code, IContainer region) throws CodegenException {
public void makeRegionIndent(ICodeWriter code, IContainer region) throws CodegenException {
code.incIndent();
makeRegion(code, region);
code.decIndent();
}
private void makeSimpleBlock(IBlock block, CodeWriter code) throws CodegenException {
private void makeSimpleBlock(IBlock block, ICodeWriter code) throws CodegenException {
if (block.contains(AFlag.DONT_GENERATE)) {
return;
}
......@@ -114,7 +121,7 @@ public class RegionGen extends InsnGen {
}
}
private void makeIf(IfRegion region, CodeWriter code, boolean newLine) throws CodegenException {
private void makeIf(IfRegion region, ICodeWriter code, boolean newLine) throws CodegenException {
if (newLine) {
code.startLineWithNum(region.getSourceLine());
} else {
......@@ -164,7 +171,7 @@ public class RegionGen extends InsnGen {
/**
* Connect if-else-if block
*/
private boolean connectElseIf(CodeWriter code, IContainer els) throws CodegenException {
private boolean connectElseIf(ICodeWriter code, IContainer els) throws CodegenException {
if (els.contains(AFlag.ELSE_IF_CHAIN) && els instanceof Region) {
List<IContainer> subBlocks = ((Region) els).getSubBlocks();
if (subBlocks.size() == 1) {
......@@ -179,7 +186,7 @@ public class RegionGen extends InsnGen {
return false;
}
private CodeWriter makeLoop(LoopRegion region, CodeWriter code) throws CodegenException {
private void makeLoop(LoopRegion region, ICodeWriter code) throws CodegenException {
LoopLabelAttr labelAttr = region.getInfo().getStart().get(AType.LOOP_LABEL);
if (labelAttr != null) {
code.startLine(mgen.getNameGen().getLoopLabel(labelAttr)).add(':');
......@@ -191,7 +198,7 @@ public class RegionGen extends InsnGen {
code.startLine("while (true) {");
makeRegionIndent(code, region.getBody());
code.startLine('}');
return code;
return;
}
ConditionGen conditionGen = new ConditionGen(this);
LoopType type = region.getType();
......@@ -207,7 +214,7 @@ public class RegionGen extends InsnGen {
code.add(") {");
makeRegionIndent(code, region.getBody());
code.startLine('}');
return code;
return;
}
if (type instanceof ForEachLoop) {
ForEachLoop forEachLoop = (ForEachLoop) type;
......@@ -218,7 +225,7 @@ public class RegionGen extends InsnGen {
code.add(") {");
makeRegionIndent(code, region.getBody());
code.startLine('}');
return code;
return;
}
throw new JadxRuntimeException("Unknown loop type: " + type.getClass());
}
......@@ -237,10 +244,9 @@ public class RegionGen extends InsnGen {
makeRegionIndent(code, region.getBody());
code.startLine('}');
}
return code;
}
private void makeSynchronizedRegion(SynchronizedRegion cont, CodeWriter code) throws CodegenException {
private void makeSynchronizedRegion(SynchronizedRegion cont, ICodeWriter code) throws CodegenException {
code.startLine("synchronized (");
addArg(code, cont.getEnterInsn().getArg(0));
code.add(") {");
......@@ -248,7 +254,7 @@ public class RegionGen extends InsnGen {
code.startLine('}');
}
private CodeWriter makeSwitch(SwitchRegion sw, CodeWriter code) throws CodegenException {
private void makeSwitch(SwitchRegion sw, ICodeWriter code) throws CodegenException {
SwitchInsn insn = (SwitchInsn) BlockUtils.getLastInsn(sw.getHeader());
Objects.requireNonNull(insn, "Switch insn not found in header");
InsnArg arg = insn.getArg(0);
......@@ -273,10 +279,9 @@ public class RegionGen extends InsnGen {
}
code.decIndent();
code.startLine('}');
return code;
}
private void addCaseKey(CodeWriter code, InsnArg arg, Object k) {
private void addCaseKey(ICodeWriter code, InsnArg arg, Object k) {
if (k instanceof FieldNode) {
FieldNode fn = (FieldNode) k;
if (fn.getParentClass().isEnum()) {
......@@ -299,7 +304,7 @@ public class RegionGen extends InsnGen {
}
}
private void makeTryCatch(TryCatchRegion region, CodeWriter code) throws CodegenException {
private void makeTryCatch(TryCatchRegion region, ICodeWriter code) throws CodegenException {
code.startLine("try {");
makeRegionIndent(code, region.getTryRegion());
// TODO: move search of 'allHandler' to 'TryCatchRegion'
......@@ -326,7 +331,7 @@ public class RegionGen extends InsnGen {
code.startLine('}');
}
private void makeCatchBlock(CodeWriter code, ExceptionHandler handler) throws CodegenException {
private void makeCatchBlock(ICodeWriter code, ExceptionHandler handler) throws CodegenException {
IContainer region = handler.getHandlerRegion();
if (region == null) {
return;
......
......@@ -14,9 +14,11 @@ import com.google.gson.GsonBuilder;
import jadx.api.CodePosition;
import jadx.api.ICodeInfo;
import jadx.api.ICodeWriter;
import jadx.api.JadxArgs;
import jadx.api.impl.AnnotatedCodeWriter;
import jadx.api.impl.SimpleCodeWriter;
import jadx.core.codegen.ClassGen;
import jadx.core.codegen.CodeWriter;
import jadx.core.codegen.MethodGen;
import jadx.core.codegen.json.cls.JsonClass;
import jadx.core.codegen.json.cls.JsonCodeLine;
......@@ -82,7 +84,7 @@ public class JsonCodeGen {
jsonCls.setInterfaces(Utils.collectionMap(cls.getInterfaces(), this::getTypeAlias));
}
CodeWriter cw = new CodeWriter();
ICodeWriter cw = new SimpleCodeWriter();
CodeGenUtils.addComments(cw, cls);
classGen.insertDecompilationProblems(cw, cls);
classGen.addClassDeclaration(cw);
......@@ -127,11 +129,10 @@ public class JsonCodeGen {
jsonField.setAlias(field.getAlias());
}
CodeWriter cw = new CodeWriter();
ICodeWriter cw = new SimpleCodeWriter();
classGen.addField(cw, field);
jsonField.setDeclaration(cw.getCodeStr());
jsonField.setAccessFlags(field.getAccessFlags().rawValue());
jsonCls.getFields().add(jsonField);
}
}
......@@ -152,7 +153,7 @@ public class JsonCodeGen {
jsonMth.setArguments(Utils.collectionMap(mth.getMethodInfo().getArgumentsTypes(), this::getTypeAlias));
MethodGen mthGen = new MethodGen(classGen, mth);
CodeWriter cw = new CodeWriter();
ICodeWriter cw = new AnnotatedCodeWriter();
mthGen.addDefinition(cw);
jsonMth.setDeclaration(cw.getCodeStr());
jsonMth.setAccessFlags(mth.getAccessFlags().rawValue());
......@@ -167,7 +168,7 @@ public class JsonCodeGen {
return Collections.emptyList();
}
CodeWriter cw = new CodeWriter();
ICodeWriter cw = mth.root().makeCodeWriter();
try {
mthGen.addInstructions(cw);
} catch (Exception e) {
......@@ -179,7 +180,7 @@ public class JsonCodeGen {
return Collections.emptyList();
}
String[] lines = codeStr.split(CodeWriter.NL);
String[] lines = codeStr.split(ICodeWriter.NL);
Map<Integer, Integer> lineMapping = code.getLineMapping();
Map<CodePosition, Object> annotations = code.getAnnotations();
long mthCodeOffset = mth.getMethodCodeOffset() + 16;
......
......@@ -3,7 +3,7 @@ package jadx.core.dex.attributes;
import java.util.ArrayList;
import java.util.List;
import jadx.core.codegen.CodeWriter;
import jadx.api.ICodeWriter;
import jadx.core.utils.Utils;
public class AttrList<T> implements IAttribute {
......@@ -26,6 +26,6 @@ public class AttrList<T> implements IAttribute {
@Override
public String toString() {
return Utils.listToString(list, CodeWriter.NL);
return Utils.listToString(list, ICodeWriter.NL);
}
}
......@@ -4,7 +4,7 @@ import java.util.Objects;
import org.jetbrains.annotations.NotNull;
import jadx.core.codegen.CodeWriter;
import jadx.api.ICodeWriter;
import jadx.core.utils.Utils;
public class JadxError implements Comparable<JadxError> {
......@@ -59,7 +59,7 @@ public class JadxError implements Comparable<JadxError> {
str.append(cause.getClass());
str.append(':');
str.append(cause.getMessage());
str.append(CodeWriter.NL);
str.append(ICodeWriter.NL);
str.append(Utils.getStackTrace(cause));
}
return str.toString();
......
......@@ -2,13 +2,12 @@ package jadx.core.dex.attributes.nodes;
import java.util.List;
import jadx.api.ICodeWriter;
import jadx.api.plugins.input.data.ILocalVar;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.IAttribute;
import jadx.core.utils.Utils;
import static jadx.core.codegen.CodeWriter.NL;
public class LocalVarsDebugInfoAttr implements IAttribute {
private final List<ILocalVar> localVars;
......@@ -27,6 +26,6 @@ public class LocalVarsDebugInfoAttr implements IAttribute {
@Override
public String toString() {
return "Debug Info:" + NL + " " + Utils.listToString(localVars, NL + " ");
return "Debug Info:" + ICodeWriter.NL + " " + Utils.listToString(localVars, ICodeWriter.NL + " ");
}
}
......@@ -3,7 +3,7 @@ package jadx.core.dex.attributes.nodes;
import java.util.LinkedList;
import java.util.List;
import jadx.core.codegen.CodeWriter;
import jadx.api.ICodeWriter;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.IAttribute;
import jadx.core.dex.instructions.PhiInsn;
......@@ -29,7 +29,7 @@ public class PhiListAttr implements IAttribute {
sb.append('r').append(phiInsn.getResult().getRegNum()).append(' ');
}
for (PhiInsn phiInsn : list) {
sb.append(CodeWriter.NL).append(" ").append(phiInsn).append(' ').append(phiInsn.getAttributesString());
sb.append(ICodeWriter.NL).append(" ").append(phiInsn).append(' ').append(phiInsn.getAttributesString());
}
return sb.toString();
}
......
......@@ -5,7 +5,7 @@ import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import jadx.core.codegen.CodeWriter;
import jadx.api.ICodeWriter;
import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.InsnNode;
......@@ -114,20 +114,20 @@ public class SwitchInsn extends TargetInsnNode {
int[] keys = switchData.getKeys();
if (targetBlocks != null) {
for (int i = 0; i < size; i++) {
sb.append(CodeWriter.NL);
sb.append(ICodeWriter.NL);
sb.append(" case ").append(keys[i]).append(": goto ").append(targetBlocks[i]);
}
if (def != -1) {
sb.append(CodeWriter.NL).append(" default: goto ").append(defTargetBlock);
sb.append(ICodeWriter.NL).append(" default: goto ").append(defTargetBlock);
}
} else {
int[] targets = switchData.getTargets();
for (int i = 0; i < size; i++) {
sb.append(CodeWriter.NL);
sb.append(ICodeWriter.NL);
sb.append(" case ").append(keys[i]).append(": goto ").append(InsnUtils.formatOffset(targets[i]));
}
if (def != -1) {
sb.append(CodeWriter.NL);
sb.append(ICodeWriter.NL);
sb.append(" default: goto ").append(InsnUtils.formatOffset(def));
}
}
......
......@@ -8,8 +8,8 @@ import java.util.Objects;
import org.jetbrains.annotations.Nullable;
import jadx.api.ICodeWriter;
import jadx.api.plugins.input.insns.InsnData;
import jadx.core.codegen.CodeWriter;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.nodes.LineAttrNode;
import jadx.core.dex.instructions.InsnType;
......@@ -477,9 +477,9 @@ public class InsnNode extends LineAttrNode {
sb.append(argsStr);
} else {
// wrap args
String separator = CodeWriter.NL + " ";
String separator = ICodeWriter.NL + " ";
sb.append(separator).append(Utils.listToString(arguments, separator));
sb.append(CodeWriter.NL);
sb.append(ICodeWriter.NL);
}
}
......
......@@ -13,6 +13,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.ICodeCache;
import jadx.api.ICodeWriter;
import jadx.api.JadxArgs;
import jadx.api.ResourceFile;
import jadx.api.ResourceType;
......@@ -435,6 +436,11 @@ public class RootNode {
}
}
public ICodeWriter makeCodeWriter() {
JadxArgs jadxArgs = this.args;
return jadxArgs.getCodeWriterProvider().apply(jadxArgs);
}
public ClspGraph getClsp() {
return clsp;
}
......
......@@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import jadx.core.codegen.CodeWriter;
import jadx.api.ICodeWriter;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IBranchRegion;
import jadx.core.dex.nodes.IContainer;
......@@ -84,7 +84,7 @@ public final class SwitchRegion extends AbstractRegion implements IBranchRegion
for (CaseInfo caseInfo : cases) {
List<String> keyStrings = Utils.collectionMap(caseInfo.getKeys(),
k -> k == DEFAULT_CASE_KEY ? "default" : k.toString());
sb.append(CodeWriter.NL).append(" case ")
sb.append(ICodeWriter.NL).append(" case ")
.append(Utils.listToString(keyStrings))
.append(" -> ").append(caseInfo.getContainer());
}
......
......@@ -5,7 +5,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import jadx.core.codegen.CodeWriter;
import jadx.api.ICodeWriter;
import jadx.api.impl.SimpleCodeWriter;
import jadx.core.codegen.MethodGen;
import jadx.core.dex.attributes.IAttributeNode;
import jadx.core.dex.instructions.IfNode;
......@@ -72,8 +73,8 @@ public class DotGraphVisitor extends AbstractVisitor {
}
private class DumpDotGraph {
private final CodeWriter dot = new CodeWriter();
private final CodeWriter conn = new CodeWriter();
private final ICodeWriter dot = new SimpleCodeWriter();
private final ICodeWriter conn = new SimpleCodeWriter();
private final File dir;
public DumpDotGraph(File dir) {
......@@ -272,7 +273,7 @@ public class DotGraphVisitor extends AbstractVisitor {
}
return str.toString();
} else {
CodeWriter code = new CodeWriter();
ICodeWriter code = new SimpleCodeWriter();
List<InsnNode> instructions = block.getInstructions();
MethodGen.addFallbackInsns(code, mth, instructions.toArray(new InsnNode[0]), BLOCK_DUMP);
String str = escape(code.newLine().toString());
......@@ -299,7 +300,7 @@ public class DotGraphVisitor extends AbstractVisitor {
.replace("\"", "\\\"")
.replace("-", "\\-")
.replace("|", "\\|")
.replace(CodeWriter.NL, NL)
.replace(ICodeWriter.NL, NL)
.replace("\n", NL);
}
}
......
......@@ -5,6 +5,7 @@ import java.util.List;
import java.util.Map;
import java.util.function.Function;
import jadx.api.ICodeWriter;
import jadx.core.Consts;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.info.MethodInfo;
......@@ -30,8 +31,6 @@ import jadx.core.dex.visitors.typeinference.TypeCompareEnum;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxRuntimeException;
import static jadx.core.codegen.CodeWriter.NL;
@JadxVisitor(
name = "MethodInvokeVisitor",
desc = "Process additional info for method invocation (overload, vararg)",
......@@ -287,10 +286,10 @@ public class MethodInvokeVisitor extends AbstractVisitor {
if (Consts.DEBUG_OVERLOADED_CASTS) {
// TODO: try to minimize casts count
parentMth.addComment("JADX DEBUG: Failed to find minimal casts for resolve overloaded methods, cast all args instead"
+ NL + " method: " + mthDetails
+ NL + " arg types: " + compilerVarTypes
+ NL + " candidates:"
+ NL + " " + Utils.listToString(overloadedMethods, NL + " "));
+ ICodeWriter.NL + " method: " + mthDetails
+ ICodeWriter.NL + " arg types: " + compilerVarTypes
+ ICodeWriter.NL + " candidates:"
+ ICodeWriter.NL + " " + Utils.listToString(overloadedMethods, ICodeWriter.NL + " "));
}
// not resolved -> cast all args
return mthDetails.getArgTypes();
......
......@@ -6,6 +6,7 @@ import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.ICodeWriter;
import jadx.api.plugins.input.data.IDebugInfo;
import jadx.api.plugins.input.data.ILocalVar;
import jadx.core.dex.attributes.nodes.LocalVarsDebugInfoAttr;
......@@ -24,8 +25,6 @@ import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxException;
import static jadx.core.codegen.CodeWriter.NL;
@JadxVisitor(
name = "Debug Info Parser",
desc = "Attach debug information (variable names and types, instruction lines)",
......@@ -48,7 +47,7 @@ public class DebugInfoAttachVisitor extends AbstractVisitor {
} catch (Exception e) {
mth.addComment("JADX WARNING: Error to parse debug info: "
+ ErrorsCounter.formatMsg(mth, e.getMessage())
+ NL + Utils.getStackTrace(e));
+ ICodeWriter.NL + Utils.getStackTrace(e));
}
}
......
......@@ -6,7 +6,8 @@ import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.core.codegen.CodeWriter;
import jadx.api.ICodeWriter;
import jadx.api.impl.SimpleCodeWriter;
import jadx.core.codegen.InsnGen;
import jadx.core.codegen.MethodGen;
import jadx.core.dex.attributes.AFlag;
......@@ -83,7 +84,7 @@ public class CheckRegions extends AbstractVisitor {
}
private static String getBlockInsnStr(MethodNode mth, IBlock block) {
CodeWriter code = new CodeWriter();
ICodeWriter code = new SimpleCodeWriter();
code.incIndent();
code.newLine();
MethodGen mg = MethodGen.getFallbackMethodGen(mth);
......@@ -96,7 +97,6 @@ public class CheckRegions extends AbstractVisitor {
}
}
code.newLine();
code.finish();
return code.toString();
return code.getCodeStr();
}
}
......@@ -2,7 +2,7 @@ package jadx.core.utils;
import java.util.List;
import jadx.core.codegen.CodeWriter;
import jadx.api.ICodeWriter;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.AttrNode;
import jadx.core.dex.attributes.nodes.RenameReasonAttr;
......@@ -14,7 +14,7 @@ import jadx.core.dex.nodes.ClassNode;
public class CodeGenUtils {
public static void addComments(CodeWriter code, AttrNode node) {
public static void addComments(ICodeWriter code, AttrNode node) {
List<String> comments = node.getAll(AType.COMMENTS);
if (!comments.isEmpty()) {
comments.stream().distinct()
......@@ -22,7 +22,7 @@ public class CodeGenUtils {
}
}
public static void addRenamedComment(CodeWriter code, AttrNode node, String origName) {
public static void addRenamedComment(ICodeWriter code, AttrNode node, String origName) {
code.startLine("/* renamed from: ").add(origName);
RenameReasonAttr renameReasonAttr = node.get(AType.RENAME_REASON);
if (renameReasonAttr != null) {
......@@ -32,7 +32,7 @@ public class CodeGenUtils {
code.add(" */");
}
public static void addSourceFileInfo(CodeWriter code, ClassNode node) {
public static void addSourceFileInfo(ICodeWriter code, ClassNode node) {
SourceFileAttr sourceFileAttr = node.get(AType.SOURCE_FILE);
if (sourceFileAttr != null) {
code.startLine("/* compiled from: ").add(sourceFileAttr.getFileName()).add(" */");
......
......@@ -3,6 +3,7 @@ package jadx.core.utils;
import java.util.ArrayList;
import java.util.List;
import jadx.api.ICodeWriter;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.PhiListAttr;
......@@ -21,8 +22,6 @@ import jadx.core.dex.visitors.PrepareForCodeGen;
import jadx.core.dex.visitors.RenameVisitor;
import jadx.core.utils.exceptions.JadxRuntimeException;
import static jadx.core.codegen.CodeWriter.NL;
/**
* Check invariants and information consistency for registers and SSA variables
*/
......@@ -89,7 +88,7 @@ public class DebugChecks {
boolean assignReg = insn.getResult() == reg;
if (!assignReg && !Utils.containsInListByRef(useList, reg)) {
throw new JadxRuntimeException("Incorrect use list in ssa var: " + sVar + ", register not listed."
+ NL + " insn: " + insn);
+ ICodeWriter.NL + " insn: " + insn);
}
for (RegisterArg useArg : useList) {
checkRegisterArg(mth, useArg);
......@@ -111,7 +110,7 @@ public class DebugChecks {
BlockNode parentInsnBlock = BlockUtils.getBlockByInsn(mth, parentInsn);
if (parentInsnBlock == null) {
throw new JadxRuntimeException("Parent insn not found in blocks tree for: " + reg
+ NL + " insn: " + parentInsn);
+ ICodeWriter.NL + " insn: " + parentInsn);
}
}
}
......
......@@ -14,7 +14,8 @@ import org.jetbrains.annotations.TestOnly;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.core.codegen.CodeWriter;
import jadx.api.ICodeWriter;
import jadx.api.impl.SimpleCodeWriter;
import jadx.core.codegen.InsnGen;
import jadx.core.codegen.MethodGen;
import jadx.core.dex.attributes.IAttributeNode;
......@@ -32,8 +33,6 @@ import jadx.core.dex.visitors.regions.TracedRegionVisitor;
import jadx.core.utils.exceptions.CodegenException;
import jadx.core.utils.exceptions.JadxException;
import static jadx.core.codegen.CodeWriter.NL;
@Deprecated
@TestOnly
public class DebugUtils {
......@@ -109,13 +108,13 @@ public class DebugUtils {
}
public static void printRegion(MethodNode mth, IRegion region, boolean printInsns) {
CodeWriter cw = new CodeWriter();
ICodeWriter cw = new SimpleCodeWriter();
cw.startLine('|').add(mth.toString());
printRegion(mth, region, cw, "| ", printInsns);
LOG.debug("{}{}", NL, cw.finish().getCodeStr());
LOG.debug("{}{}", ICodeWriter.NL, cw.finish().getCodeStr());
}
private static void printRegion(MethodNode mth, IRegion region, CodeWriter cw, String indent, boolean printInsns) {
private static void printRegion(MethodNode mth, IRegion region, ICodeWriter cw, String indent, boolean printInsns) {
printWithAttributes(cw, indent, region.toString(), region);
indent += "| ";
for (IContainer container : region.getSubBlocks()) {
......@@ -131,16 +130,16 @@ public class DebugUtils {
}
}
private static void printInsns(MethodNode mth, CodeWriter cw, String indent, IBlock block) {
private static void printInsns(MethodNode mth, ICodeWriter cw, String indent, IBlock block) {
for (InsnNode insn : block.getInstructions()) {
try {
MethodGen mg = MethodGen.getFallbackMethodGen(mth);
InsnGen ig = new InsnGen(mg, true);
CodeWriter code = new CodeWriter();
ICodeWriter code = new SimpleCodeWriter();
ig.makeInsn(insn, code);
String codeStr = code.finish().getCodeStr();
String codeStr = code.getCodeStr();
List<String> insnStrings = Stream.of(codeStr.split(NL))
List<String> insnStrings = Stream.of(codeStr.split(ICodeWriter.NL))
.filter(StringUtils::notBlank)
.map(s -> "|> " + s)
.collect(Collectors.toList());
......@@ -160,9 +159,9 @@ public class DebugUtils {
}
}
private static void printWithAttributes(CodeWriter cw, String indent, String codeStr, IAttributeNode attrNode) {
private static void printWithAttributes(ICodeWriter cw, String indent, String codeStr, IAttributeNode attrNode) {
String str = attrNode.isAttrStorageEmpty() ? codeStr : codeStr + ' ' + attrNode.getAttributesString();
List<String> attrStrings = Stream.of(str.split(NL))
List<String> attrStrings = Stream.of(str.split(ICodeWriter.NL))
.filter(StringUtils::notBlank)
.collect(Collectors.toList());
Iterator<String> it = attrStrings.iterator();
......
......@@ -7,6 +7,7 @@ import java.util.stream.Collectors;
import org.jetbrains.annotations.Nullable;
import jadx.api.ICodeWriter;
import jadx.core.Consts;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.instructions.InsnType;
......@@ -20,8 +21,6 @@ import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.utils.exceptions.JadxRuntimeException;
import static jadx.core.codegen.CodeWriter.NL;
/**
* Helper class for correct instructions removing,
* can be used while iterating over instructions list
......@@ -137,9 +136,9 @@ public class InsnRemover {
}
if (Consts.DEBUG_WITH_ERRORS) {
throw new JadxRuntimeException("Can't remove SSA var, still in use, count: " + useCount + ", list:"
+ NL + " " + ssaVar.getUseList().stream()
+ ICodeWriter.NL + " " + ssaVar.getUseList().stream()
.map(arg -> arg + " from " + arg.getParentInsn())
.collect(Collectors.joining(NL + " ")));
.collect(Collectors.joining(ICodeWriter.NL + " ")));
}
}
......@@ -174,9 +173,9 @@ public class InsnRemover {
}
if (!found && Consts.DEBUG_WITH_ERRORS) {
throw new JadxRuntimeException("Can't remove insn:"
+ NL + " " + rem
+ NL + " not found in list:"
+ NL + " " + Utils.listToString(insns, NL + " "));
+ ICodeWriter.NL + " " + rem
+ ICodeWriter.NL + " not found in list:"
+ ICodeWriter.NL + " " + Utils.listToString(insns, ICodeWriter.NL + " "));
}
}
}
......
......@@ -16,8 +16,8 @@ import java.util.function.Function;
import org.jetbrains.annotations.Nullable;
import jadx.api.ICodeWriter;
import jadx.api.JadxDecompiler;
import jadx.core.codegen.CodeWriter;
import jadx.core.dex.visitors.DepthTraversal;
public class Utils {
......@@ -124,7 +124,7 @@ public class Utils {
return sw.getBuffer().toString();
}
public static void appendStackTrace(CodeWriter code, Throwable throwable) {
public static void appendStackTrace(ICodeWriter code, Throwable throwable) {
if (throwable == null) {
return;
}
......
......@@ -9,11 +9,11 @@ import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.ICodeWriter;
import jadx.api.plugins.input.data.AccessFlags;
import jadx.api.plugins.input.data.annotations.EncodedType;
import jadx.api.plugins.input.data.annotations.EncodedValue;
import jadx.core.codegen.ClassGen;
import jadx.core.codegen.CodeWriter;
import jadx.core.deobf.NameMapper;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
......@@ -63,7 +63,7 @@ public class AndroidResourcesUtils {
return newResCls;
}
public static boolean handleAppResField(CodeWriter code, ClassGen clsGen, ClassInfo declClass) {
public static boolean handleAppResField(ICodeWriter code, ClassGen clsGen, ClassInfo declClass) {
ClassInfo parentClass = declClass.getParentClass();
if (parentClass != null && parentClass.getShortName().equals("R")) {
clsGen.useClass(code, parentClass);
......
......@@ -2,10 +2,9 @@ package jadx.core.utils.exceptions;
import java.util.Arrays;
import jadx.api.ICodeWriter;
import jadx.core.utils.Utils;
import static jadx.core.codegen.CodeWriter.NL;
public class JadxRuntimeException extends RuntimeException {
private static final long serialVersionUID = -7410848445429898248L;
......@@ -15,7 +14,7 @@ public class JadxRuntimeException extends RuntimeException {
}
public JadxRuntimeException(String... lines) {
super(Utils.listToString(Arrays.asList(lines), NL + " "));
super(Utils.listToString(Arrays.asList(lines), ICodeWriter.NL + " "));
}
public JadxRuntimeException(String message, Throwable cause) {
......
......@@ -12,8 +12,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.ICodeInfo;
import jadx.api.ICodeWriter;
import jadx.api.ResourcesLoader;
import jadx.core.codegen.CodeWriter;
import jadx.core.dex.info.ConstStorage;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.RootNode;
......@@ -43,7 +43,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
private Set<String> nsMapGenerated;
private final Map<String, String> tagAttrDeobfNames = new HashMap<>();
private CodeWriter writer;
private ICodeWriter writer;
private String[] strings;
private String currentTag = "ERROR";
private boolean firstElement;
......@@ -73,7 +73,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
}
nsMapGenerated = new HashSet<>();
nsMap = new HashMap<>();
writer = new CodeWriter();
writer = rootNode.makeCodeWriter();
writer.add("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
firstElement = true;
decode();
......@@ -443,7 +443,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
return sb.toString();
}
private void attachClassNode(CodeWriter writer, String attrName, String clsName) {
private void attachClassNode(ICodeWriter writer, String attrName, String clsName) {
if (clsName == null || !attrName.equals("name")) {
return;
}
......
......@@ -14,7 +14,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.ICodeInfo;
import jadx.core.codegen.CodeWriter;
import jadx.api.ICodeWriter;
import jadx.core.deobf.NameMapper;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.nodes.FieldNode;
......@@ -95,7 +95,7 @@ public class ResTableParser extends CommonBinaryParser {
}
public ICodeInfo makeXmlDump() {
CodeWriter writer = new CodeWriter();
ICodeWriter writer = root.makeCodeWriter();
writer.startLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
writer.startLine("<resources>");
writer.incIndent();
......
......@@ -10,7 +10,8 @@ import java.util.Map;
import java.util.Set;
import jadx.api.ICodeInfo;
import jadx.core.codegen.CodeWriter;
import jadx.api.ICodeWriter;
import jadx.api.impl.SimpleCodeWriter;
import jadx.core.utils.StringUtils;
import jadx.core.xmlgen.entry.RawNamedValue;
import jadx.core.xmlgen.entry.ResourceEntry;
......@@ -35,15 +36,15 @@ public class ResXmlGen {
}
public List<ResContainer> makeResourcesXml() {
Map<String, CodeWriter> contMap = new HashMap<>();
Map<String, ICodeWriter> contMap = new HashMap<>();
for (ResourceEntry ri : resStorage.getResources()) {
if (SKIP_RES_TYPES.contains(ri.getTypeName())) {
continue;
}
String fn = getFileName(ri);
CodeWriter cw = contMap.get(fn);
ICodeWriter cw = contMap.get(fn);
if (cw == null) {
cw = new CodeWriter();
cw = new SimpleCodeWriter();
cw.add("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
cw.startLine("<resources>");
cw.incIndent();
......@@ -53,10 +54,9 @@ public class ResXmlGen {
}
List<ResContainer> files = new ArrayList<>(contMap.size());
for (Map.Entry<String, CodeWriter> entry : contMap.entrySet()) {
for (Map.Entry<String, ICodeWriter> entry : contMap.entrySet()) {
String fileName = entry.getKey();
CodeWriter content = entry.getValue();
ICodeWriter content = entry.getValue();
content.decIndent();
content.startLine("</resources>");
ICodeInfo codeInfo = content.finish();
......@@ -66,7 +66,7 @@ public class ResXmlGen {
return files;
}
private void addValue(CodeWriter cw, ResourceEntry ri) {
private void addValue(ICodeWriter cw, ResourceEntry ri) {
if (ri.getSimpleValue() != null) {
String valueStr = vp.decodeValue(ri.getSimpleValue());
addSimpleValue(cw, ri.getTypeName(), ri.getTypeName(), "name", ri.getKeyName(), valueStr);
......@@ -137,7 +137,7 @@ public class ResXmlGen {
return s.substring(1);
}
private void addItem(CodeWriter cw, String itemTag, String typeName, RawNamedValue value) {
private void addItem(ICodeWriter cw, String itemTag, String typeName, RawNamedValue value) {
String nameStr = vp.decodeNameRef(value.getNameRef());
String valueStr = vp.decodeValue(value.getRawValue());
if (!typeName.equals("attr")) {
......@@ -177,7 +177,7 @@ public class ResXmlGen {
}
}
private void addSimpleValue(CodeWriter cw, String typeName, String itemTag, String attrName, String attrValue, String valueStr) {
private void addSimpleValue(ICodeWriter cw, String typeName, String itemTag, String attrName, String attrValue, String valueStr) {
if (valueStr == null) {
return;
}
......
......@@ -26,10 +26,10 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import jadx.api.ICodeInfo;
import jadx.api.ICodeWriter;
import jadx.api.JadxArgs;
import jadx.api.JadxDecompiler;
import jadx.api.JadxInternalAccess;
import jadx.core.codegen.CodeWriter;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.AttrList;
......@@ -240,7 +240,7 @@ public abstract class IntegrationTest extends TestUtils {
private void printCodeWithLineNumbers(ICodeInfo code) {
String codeStr = code.getCodeStr();
Map<Integer, Integer> lineMapping = code.getLineMapping();
String[] lines = codeStr.split(CodeWriter.NL);
String[] lines = codeStr.split(ICodeWriter.NL);
for (int i = 0; i < lines.length; i++) {
String line = lines[i];
int curLine = i + 1;
......
......@@ -2,7 +2,7 @@ package jadx.tests.api.utils;
import org.hamcrest.Matcher;
import jadx.core.codegen.CodeWriter;
import jadx.api.ICodeWriter;
public class JadxMatchers {
......@@ -17,7 +17,7 @@ public class JadxMatchers {
public static Matcher<String> containsLines(String... lines) {
StringBuilder sb = new StringBuilder();
for (String line : lines) {
sb.append(line).append(CodeWriter.NL);
sb.append(line).append(ICodeWriter.NL);
}
return countString(1, sb.toString());
}
......@@ -30,7 +30,7 @@ public class JadxMatchers {
sb.append(indent);
sb.append(line);
}
sb.append(CodeWriter.NL);
sb.append(ICodeWriter.NL);
}
return countString(1, sb.toString());
}
......
......@@ -3,22 +3,22 @@ package jadx.tests.api.utils;
import org.junit.jupiter.api.extension.ExtendWith;
import jadx.NotYetImplementedExtension;
import jadx.core.codegen.CodeWriter;
import jadx.api.ICodeWriter;
@ExtendWith(NotYetImplementedExtension.class)
public class TestUtils {
public static String indent() {
return CodeWriter.INDENT_STR;
return ICodeWriter.INDENT_STR;
}
public static String indent(int indent) {
if (indent == 1) {
return CodeWriter.INDENT_STR;
return ICodeWriter.INDENT_STR;
}
StringBuilder sb = new StringBuilder(indent * CodeWriter.INDENT_STR.length());
StringBuilder sb = new StringBuilder(indent * ICodeWriter.INDENT_STR.length());
for (int i = 0; i < indent; i++) {
sb.append(CodeWriter.INDENT_STR);
sb.append(ICodeWriter.INDENT_STR);
}
return sb.toString();
}
......
......@@ -2,7 +2,7 @@ package jadx.tests.api.utils.assertj;
import org.assertj.core.api.AbstractStringAssert;
import jadx.core.codegen.CodeWriter;
import jadx.api.ICodeWriter;
import jadx.tests.api.utils.TestUtils;
public class JadxCodeAssertions extends AbstractStringAssert<JadxCodeAssertions> {
......@@ -52,7 +52,7 @@ public class JadxCodeAssertions extends AbstractStringAssert<JadxCodeAssertions>
if (first) {
first = false;
} else {
sb.append(CodeWriter.NL);
sb.append(ICodeWriter.NL);
}
sb.append(indent);
sb.append(line);
......
......@@ -10,11 +10,11 @@ import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.ICodeWriter;
import jadx.api.JadxArgs;
import jadx.api.JadxDecompiler;
import jadx.api.JadxInternalAccess;
import jadx.api.JavaClass;
import jadx.core.codegen.CodeWriter;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.RootNode;
......@@ -130,7 +130,7 @@ public abstract class BaseExternalTest extends IntegrationTest {
String dashLine = "======================================================================================";
Map<Integer, MethodNode> methodsMap = getMethodsMap(classNode);
String[] lines = code.split(CodeWriter.NL);
String[] lines = code.split(ICodeWriter.NL);
for (MethodNode mth : classNode.getMethods()) {
if (isMthMatch(mth, mthPattern)) {
int decompiledLine = mth.getDecompiledLine() - 1;
......@@ -144,7 +144,7 @@ public abstract class BaseExternalTest extends IntegrationTest {
break;
}
String line = lines[i];
mthCode.append(line).append(CodeWriter.NL);
mthCode.append(line).append(ICodeWriter.NL);
// also count brackets for detect method end
if (i >= decompiledLine) {
brackets += StringUtils.countMatches(line, '{');
......@@ -173,7 +173,7 @@ public abstract class BaseExternalTest extends IntegrationTest {
protected int getCommentLinesCount(String[] lines, int line) {
for (int i = line - 1; i > 0 && i < lines.length; i--) {
String str = lines[i];
if (str.isEmpty() || str.equals(CodeWriter.NL)) {
if (str.isEmpty() || str.equals(ICodeWriter.NL)) {
return i + 1;
}
}
......
......@@ -2,7 +2,7 @@ package jadx.tests.integration.debuginfo;
import org.junit.jupiter.api.Test;
import jadx.core.codegen.CodeWriter;
import jadx.api.ICodeWriter;
import jadx.core.dex.attributes.nodes.LineAttrNode;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.FieldNode;
......@@ -61,7 +61,7 @@ public class TestLineNumbers extends IntegrationTest {
assertEquals(testClassLine + 20, innerFunc3.getSourceLine());
// check decompiled lines
String[] lines = code.split(CodeWriter.NL);
String[] lines = code.split(ICodeWriter.NL);
checkLine(lines, field, "int field;");
checkLine(lines, func, "public void func() {");
checkLine(lines, inner, "public static class Inner {");
......
......@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
import jadx.NotYetImplemented;
import jadx.api.ICodeInfo;
import jadx.core.codegen.CodeWriter;
import jadx.api.ICodeWriter;
import jadx.core.dex.attributes.nodes.LineAttrNode;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.MethodNode;
......@@ -54,7 +54,7 @@ public class TestReturnSourceLine extends IntegrationTest {
ClassNode cls = getClassNode(TestCls.class);
ICodeInfo codeInfo = cls.getCode();
String code = codeInfo.toString();
String[] lines = code.split(CodeWriter.NL);
String[] lines = code.split(ICodeWriter.NL);
MethodNode test1 = cls.searchMethodByShortId("test1(Z)I");
checkLine(lines, codeInfo, test1, 3, "return 1;");
......@@ -69,7 +69,7 @@ public class TestReturnSourceLine extends IntegrationTest {
ClassNode cls = getClassNode(TestCls.class);
ICodeInfo codeInfo = cls.getCode();
String code = codeInfo.toString();
String[] lines = code.split(CodeWriter.NL);
String[] lines = code.split(ICodeWriter.NL);
MethodNode test3 = cls.searchMethodByShortId("test3(I)I");
checkLine(lines, codeInfo, test3, 3, "return v;");
......
......@@ -9,7 +9,7 @@ import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;
import javax.swing.*;
import javax.swing.ProgressMonitor;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
......
......@@ -6,8 +6,8 @@ import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.ICodeWriter;
import jadx.api.JavaClass;
import jadx.core.codegen.CodeWriter;
import jadx.gui.JadxWrapper;
import jadx.gui.utils.CacheObject;
import jadx.gui.utils.CodeLinesInfo;
......@@ -77,7 +77,7 @@ public class IndexJob extends BackgroundJob {
@NotNull
protected static List<StringRef> splitLines(JavaClass cls) {
List<StringRef> lines = StringRef.split(cls.getCode(), CodeWriter.NL);
List<StringRef> lines = StringRef.split(cls.getCode(), ICodeWriter.NL);
int size = lines.size();
for (int i = 0; i < size; i++) {
lines.set(i, lines.get(i).trim());
......
......@@ -12,6 +12,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import jadx.api.ICodeInfo;
import jadx.api.ICodeWriter;
import jadx.api.ResourceFile;
import jadx.api.ResourceFileContent;
import jadx.api.ResourceType;
......@@ -23,8 +24,6 @@ import jadx.gui.utils.NLS;
import jadx.gui.utils.OverlayIcon;
import jadx.gui.utils.UiUtils;
import static jadx.core.codegen.CodeWriter.NL;
public class JResource extends JLoadableNode implements Comparable<JResource> {
private static final long serialVersionUID = -201018424302612434L;
......@@ -154,7 +153,7 @@ public class JResource extends JLoadableNode implements Comparable<JResource> {
return ResourcesLoader.loadToCodeWriter(is);
});
} catch (Exception e) {
return new SimpleCodeInfo("Failed to load resource file:" + NL + Utils.getStackTrace(e));
return new SimpleCodeInfo("Failed to load resource file:" + ICodeWriter.NL + Utils.getStackTrace(e));
}
case DECODED_DATA:
......
......@@ -10,6 +10,7 @@ import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import hu.kazocsaba.imageviewer.ImageViewer;
import jadx.api.ICodeWriter;
import jadx.api.ResourceFile;
import jadx.api.ResourcesLoader;
import jadx.core.utils.Utils;
......@@ -18,8 +19,6 @@ import jadx.core.xmlgen.ResContainer;
import jadx.gui.treemodel.JResource;
import jadx.gui.ui.codearea.AbstractCodeArea;
import static jadx.core.codegen.CodeWriter.NL;
public class ImagePanel extends ContentPanel {
private static final long serialVersionUID = 4071356367073142688L;
......@@ -32,7 +31,7 @@ public class ImagePanel extends ContentPanel {
add(imageViewer.getComponent());
} catch (Exception e) {
RSyntaxTextArea textArea = AbstractCodeArea.getDefaultArea(panel.getMainWindow());
textArea.setText("Image load error:" + NL + Utils.getStackTrace(e));
textArea.setText("Image load error:" + ICodeWriter.NL + Utils.getStackTrace(e));
add(textArea);
}
}
......
......@@ -24,7 +24,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.*;
import jadx.core.codegen.CodeWriter;
import jadx.core.deobf.DeobfPresets;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.MethodOverrideAttr;
......@@ -70,16 +69,16 @@ public class RenameDialog extends JDialog {
public static boolean checkSettings(MainWindow mainWindow) {
StringBuilder errorMessage = new StringBuilder();
errorMessage.append(NLS.str("msg.rename_disabled")).append(CodeWriter.NL);
errorMessage.append(NLS.str("msg.rename_disabled")).append(ICodeWriter.NL);
JadxSettings settings = mainWindow.getSettings();
boolean valid = true;
if (!settings.isDeobfuscationOn()) {
errorMessage.append(" - ").append(NLS.str("msg.rename_disabled_deobfuscation_disabled")).append(CodeWriter.NL);
errorMessage.append(" - ").append(NLS.str("msg.rename_disabled_deobfuscation_disabled")).append(ICodeWriter.NL);
valid = false;
}
if (settings.isDeobfuscationForceSave()) {
errorMessage.append(" - ").append(NLS.str("msg.rename_disabled_force_rewrite_enabled")).append(CodeWriter.NL);
errorMessage.append(" - ").append(NLS.str("msg.rename_disabled_force_rewrite_enabled")).append(ICodeWriter.NL);
valid = false;
}
if (valid) {
......
......@@ -212,13 +212,13 @@ public class ResourceIndex {
extSet.add(ext);
}
}
ZipFile zipFile = getZipFile(cache.getJRoot());
traverseTree(cache.getJRoot(), zipFile); // reindex
try {
ZipFile zipFile = getZipFile(cache.getJRoot());
traverseTree(cache.getJRoot(), zipFile); // reindex
if (zipFile != null) {
zipFile.close();
}
} catch (IOException e) {
} catch (Exception e) {
e.printStackTrace();
}
}
......
......@@ -11,11 +11,11 @@ import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.FlowableEmitter;
import jadx.api.ICodeWriter;
import jadx.api.JavaClass;
import jadx.api.JavaField;
import jadx.api.JavaMethod;
import jadx.api.JavaNode;
import jadx.core.codegen.CodeWriter;
import jadx.gui.treemodel.CodeNode;
import jadx.gui.treemodel.JNode;
import jadx.gui.ui.SearchDialog;
......@@ -161,13 +161,12 @@ public class TextSearchIndex {
}
private int searchNext(FlowableEmitter<CodeNode> emitter, JavaNode javaClass, String code, final SearchSettings searchSettings) {
int pos;
pos = searchSettings.find(code);
int pos = searchSettings.find(code);
if (pos == -1) {
return -1;
}
int lineStart = 1 + code.lastIndexOf(CodeWriter.NL, pos);
int lineEnd = code.indexOf(CodeWriter.NL, pos + searchSettings.getSearchString().length());
int lineStart = 1 + code.lastIndexOf(ICodeWriter.NL, pos);
int lineEnd = code.indexOf(ICodeWriter.NL, pos + searchSettings.getSearchString().length());
StringRef line = StringRef.subString(code, lineStart, lineEnd == -1 ? code.length() : lineEnd);
emitter.onNext(new CodeNode(nodeCache.makeFrom(javaClass), -pos, line.trim()).setPos(pos));
return lineEnd;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册