diff --git a/jadx-cli/src/main/java/jadx/cli/JadxCLI.java b/jadx-cli/src/main/java/jadx/cli/JadxCLI.java index 7cec8c6cac215ef73d91d59f942950c85b4b81fb..83880ee4bae8982e36ca7426ce740fb51a02f31b 100644 --- a/jadx-cli/src/main/java/jadx/cli/JadxCLI.java +++ b/jadx-cli/src/main/java/jadx/cli/JadxCLI.java @@ -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(); diff --git a/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java b/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java index a68a75c74e28dc8a10d3499b446cf0ef65b3a04e..c28d7074d5b3ff61480534f4c650ec84a4d37020 100644 --- a/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java +++ b/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java @@ -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; } diff --git a/jadx-core/src/main/java/jadx/api/ICodeWriter.java b/jadx-core/src/main/java/jadx/api/ICodeWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..d46b5044e8d6624289d68401835305f1a19f471a --- /dev/null +++ b/jadx-core/src/main/java/jadx/api/ICodeWriter.java @@ -0,0 +1,54 @@ +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(); +} diff --git a/jadx-core/src/main/java/jadx/api/JadxArgs.java b/jadx-core/src/main/java/jadx/api/JadxArgs.java index 6b2f8f143fbe45da1ac505a45b7555b9693c4ca7..4864bea76d2202cf860a2cd07e79e631849b9dfa 100644 --- a/jadx-core/src/main/java/jadx/api/JadxArgs.java +++ b/jadx-core/src/main/java/jadx/api/JadxArgs.java @@ -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 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 getCodeWriterProvider() { + return codeWriterProvider; + } + + public void setCodeWriterProvider(Function 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() + '}'; } } diff --git a/jadx-core/src/main/java/jadx/api/ResourcesLoader.java b/jadx-core/src/main/java/jadx/api/ResourcesLoader.java index 224705503ca543dbc8a4fd0158731a646794cb07..8787b3ede3c777ef456a25f034c76353f14b73df 100644 --- a/jadx-core/src/main/java/jadx/api/ResourcesLoader.java +++ b/jadx-core/src/main/java/jadx/api/ResourcesLoader.java @@ -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()); diff --git a/jadx-core/src/main/java/jadx/api/impl/AnnotatedCodeInfo.java b/jadx-core/src/main/java/jadx/api/impl/AnnotatedCodeInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..afc5ff600a1408102accb895b9def2c413db6dba --- /dev/null +++ b/jadx-core/src/main/java/jadx/api/impl/AnnotatedCodeInfo.java @@ -0,0 +1,43 @@ +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 lineMapping; + private final Map annotations; + + public AnnotatedCodeInfo(ICodeInfo codeInfo) { + this(codeInfo.getCodeStr(), codeInfo.getLineMapping(), codeInfo.getAnnotations()); + } + + public AnnotatedCodeInfo(String code, Map lineMapping, Map annotations) { + this.code = code; + this.lineMapping = lineMapping; + this.annotations = annotations; + } + + @Override + public String getCodeStr() { + return code; + } + + @Override + public Map getLineMapping() { + return lineMapping; + } + + @Override + public Map getAnnotations() { + return annotations; + } + + @Override + public String toString() { + return code; + } +} diff --git a/jadx-core/src/main/java/jadx/api/impl/AnnotatedCodeWriter.java b/jadx-core/src/main/java/jadx/api/impl/AnnotatedCodeWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..7a7c1072d4e7595155e88c84385a5bc028bb184d --- /dev/null +++ b/jadx-core/src/main/java/jadx/api/impl/AnnotatedCodeWriter.java @@ -0,0 +1,181 @@ +package jadx.api.impl; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +import jadx.api.CodePosition; +import jadx.api.ICodeInfo; +import jadx.api.ICodeWriter; +import jadx.api.JadxArgs; +import jadx.core.dex.attributes.nodes.LineAttrNode; +import jadx.core.utils.StringUtils; + +public class AnnotatedCodeWriter extends SimpleCodeWriter implements ICodeWriter { + + private int line = 1; + private int offset; + private Map annotations = Collections.emptyMap(); + private Map lineMap = Collections.emptyMap(); + + public AnnotatedCodeWriter() { + } + + public AnnotatedCodeWriter(JadxArgs args) { + super(args); + } + + @Override + public boolean isMetadataSupported() { + return true; + } + + @Override + public AnnotatedCodeWriter addMultiLine(String str) { + if (str.contains(NL)) { + buf.append(str.replace(NL, NL + indentStr)); + line += StringUtils.countMatches(str, NL); + offset = 0; + } else { + buf.append(str); + } + return this; + } + + @Override + public AnnotatedCodeWriter add(String str) { + buf.append(str); + offset += str.length(); + return this; + } + + @Override + public AnnotatedCodeWriter add(char c) { + buf.append(c); + offset++; + return this; + } + + @Override + public ICodeWriter add(ICodeWriter cw) { + if ((!(cw instanceof AnnotatedCodeWriter))) { + buf.append(cw.getCodeStr()); + return this; + } + AnnotatedCodeWriter code = ((AnnotatedCodeWriter) cw); + line--; + for (Map.Entry entry : code.annotations.entrySet()) { + Object val = entry.getValue(); + if (val instanceof DefinitionWrapper) { + LineAttrNode node = ((DefinitionWrapper) val).getNode(); + node.setDefPosition(node.getDefPosition() + this.buf.length()); + } + CodePosition pos = entry.getKey(); + int usagePos = pos.getUsagePosition() + getLength(); + attachAnnotation(val, + new CodePosition(line + pos.getLine(), pos.getOffset()) + .setUsagePosition(usagePos)); + } + for (Map.Entry entry : code.lineMap.entrySet()) { + attachSourceLine(line + entry.getKey(), entry.getValue()); + } + line += code.line; + offset = code.offset; + buf.append(code.buf); + return this; + } + + @Override + protected void addLine() { + buf.append(NL); + line++; + offset = 0; + } + + @Override + protected AnnotatedCodeWriter addLineIndent() { + buf.append(indentStr); + offset += indentStr.length(); + return this; + } + + @Override + public int getLine() { + return line; + } + + private static final class DefinitionWrapper { + private final LineAttrNode node; + + private DefinitionWrapper(LineAttrNode node) { + this.node = node; + } + + public LineAttrNode getNode() { + return node; + } + } + + @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(getLength())); + } + + @Override + public void attachLineAnnotation(Object obj) { + attachAnnotation(obj, new CodePosition(line, 0)); + } + + private void attachAnnotation(Object obj, CodePosition pos) { + if (annotations.isEmpty()) { + annotations = new HashMap<>(); + } + annotations.put(pos, obj); + } + + @Override + public void attachSourceLine(int sourceLine) { + if (sourceLine == 0) { + return; + } + attachSourceLine(line, sourceLine); + } + + private void attachSourceLine(int decompiledLine, int sourceLine) { + if (lineMap.isEmpty()) { + lineMap = new TreeMap<>(); + } + lineMap.put(decompiledLine, sourceLine); + } + + @Override + public ICodeInfo finish() { + removeFirstEmptyLine(); + processDefinitionAnnotations(); + String code = buf.toString(); + buf = null; + return new AnnotatedCodeInfo(code, lineMap, annotations); + } + + private void processDefinitionAnnotations() { + if (!annotations.isEmpty()) { + annotations.entrySet().removeIf(entry -> { + Object v = entry.getValue(); + if (v instanceof DefinitionWrapper) { + LineAttrNode l = ((DefinitionWrapper) v).getNode(); + l.setDecompiledLine(entry.getKey().getLine()); + return true; + } + return false; + }); + } + } +} diff --git a/jadx-core/src/main/java/jadx/api/impl/SimpleCodeInfo.java b/jadx-core/src/main/java/jadx/api/impl/SimpleCodeInfo.java index e6822a872cae57eca46a44c8f4711b4f8f7c9bd8..c3d4582bd4e1a5b2dec5fe8e5c0eda78385f2aff 100644 --- a/jadx-core/src/main/java/jadx/api/impl/SimpleCodeInfo.java +++ b/jadx-core/src/main/java/jadx/api/impl/SimpleCodeInfo.java @@ -9,21 +9,9 @@ import jadx.api.ICodeInfo; public class SimpleCodeInfo implements ICodeInfo { private final String code; - private final Map lineMapping; - private final Map 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 lineMapping, Map annotations) { this.code = code; - this.lineMapping = lineMapping; - this.annotations = annotations; } @Override @@ -33,12 +21,12 @@ public class SimpleCodeInfo implements ICodeInfo { @Override public Map getLineMapping() { - return lineMapping; + return Collections.emptyMap(); } @Override public Map getAnnotations() { - return annotations; + return Collections.emptyMap(); } @Override diff --git a/jadx-core/src/main/java/jadx/api/impl/SimpleCodeWriter.java b/jadx-core/src/main/java/jadx/api/impl/SimpleCodeWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..704531abbedcee4a3328c281db3210193310de9a --- /dev/null +++ b/jadx-core/src/main/java/jadx/api/impl/SimpleCodeWriter.java @@ -0,0 +1,241 @@ +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(); + } +} diff --git a/jadx-core/src/main/java/jadx/core/codegen/AnnotationGen.java b/jadx-core/src/main/java/jadx/core/codegen/AnnotationGen.java index e66f79fd05ca3d2509434ebacd8ed92571b1dd69..62488cc1ef5adb1c71a6842a127fd10e507ec012 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/AnnotationGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/AnnotationGen.java @@ -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 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 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; diff --git a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java index e67bf94adf0ab6e7a9ed1aecbbb96cf525927416..987f1a5c451a063076c21c16c81eb7f991042440 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java @@ -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 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 generics, boolean classDeclaration) { + public boolean addGenericTypeParameters(ICodeWriter code, List 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 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 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 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 useInMths = fieldNode.getUseIn(); code.startLine("// use in methods - ").add(Integer.toString(useInMths.size())); for (MethodNode useMth : useInMths) { diff --git a/jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java b/jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java deleted file mode 100644 index 2c7caa4a000e1569e7e84b55a4aeff56c9822baa..0000000000000000000000000000000000000000 --- a/jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java +++ /dev/null @@ -1,301 +0,0 @@ -package jadx.core.codegen; - -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.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; - - private int line = 1; - private int offset = 0; - private Map annotations = Collections.emptyMap(); - private Map 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 CodeWriter startLine(String str) { - addLine(); - addLineIndent(); - add(str); - return this; - } - - 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; - } - - public CodeWriter addMultiLine(String str) { - if (str.contains(NL)) { - buf.append(str.replace(NL, NL + indentStr)); - line += StringUtils.countMatches(str, NL); - offset = 0; - } else { - buf.append(str); - } - return this; - } - - public CodeWriter add(String str) { - buf.append(str); - offset += str.length(); - return this; - } - - public CodeWriter add(char c) { - buf.append(c); - offset++; - return this; - } - - CodeWriter add(CodeWriter code) { - line--; - for (Map.Entry entry : code.annotations.entrySet()) { - Object val = entry.getValue(); - if (val instanceof DefinitionWrapper) { - LineAttrNode node = ((DefinitionWrapper) val).getNode(); - node.setDefPosition(node.getDefPosition() + this.buf.length()); - } - CodePosition pos = entry.getKey(); - int usagePos = pos.getUsagePosition() + bufLength(); - attachAnnotation(val, - new CodePosition(line + pos.getLine(), pos.getOffset()) - .setUsagePosition(usagePos)); - } - for (Map.Entry entry : code.lineMap.entrySet()) { - attachSourceLine(line + entry.getKey(), entry.getValue()); - } - line += code.line; - offset = code.offset; - buf.append(code.buf); - return this; - } - - public CodeWriter newLine() { - addLine(); - return this; - } - - public CodeWriter addIndent() { - add(INDENT_STR); - return this; - } - - private void addLine() { - buf.append(NL); - line++; - offset = 0; - } - - private CodeWriter 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(); - } - - public int getLine() { - return line; - } - - private static class DefinitionWrapper { - private final LineAttrNode node; - - private DefinitionWrapper(LineAttrNode node) { - this.node = node; - } - - public LineAttrNode getNode() { - return node; - } - } - - public void attachDefinition(LineAttrNode obj) { - obj.setDefPosition(buf.length()); - attachAnnotation(obj); - attachAnnotation(new DefinitionWrapper(obj), new CodePosition(line, offset)); - } - - public void attachAnnotation(Object obj) { - attachAnnotation(obj, - new CodePosition(line, offset + 1).setUsagePosition(bufLength())); - } - - public void attachLineAnnotation(Object obj) { - attachAnnotation(obj, new CodePosition(line, 0)); - } - - private Object attachAnnotation(Object obj, CodePosition pos) { - if (annotations.isEmpty()) { - annotations = new HashMap<>(); - } - return annotations.put(pos, obj); - } - - public void attachSourceLine(int sourceLine) { - if (sourceLine == 0) { - return; - } - attachSourceLine(line, sourceLine); - } - - private void attachSourceLine(int decompiledLine, int sourceLine) { - if (lineMap.isEmpty()) { - lineMap = new TreeMap<>(); - } - lineMap.put(decompiledLine, sourceLine); - } - - public ICodeInfo finish() { - removeFirstEmptyLine(); - processDefinitionAnnotations(); - 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); - } - } - - private void processDefinitionAnnotations() { - if (!annotations.isEmpty()) { - annotations.entrySet().removeIf(entry -> { - Object v = entry.getValue(); - if (v instanceof DefinitionWrapper) { - LineAttrNode l = ((DefinitionWrapper) v).getNode(); - l.setDecompiledLine(entry.getKey().getLine()); - return true; - } - return false; - }); - } - } - - 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(); - } -} diff --git a/jadx-core/src/main/java/jadx/core/codegen/ConditionGen.java b/jadx-core/src/main/java/jadx/core/codegen/ConditionGen.java index ee3ed1fb36c1dec5d92264d8d7a726e4dcd27608..a8fd45d42efb82bc64a157e989ec39104b8f046a 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/ConditionGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/ConditionGen.java @@ -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 it = condition.getArgs().iterator(); while (it.hasNext()) { diff --git a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java index 770a416908d7b7c0b9db01bb339545b3a6a1816d..e41e94097ff0c90a64e3a79cacf1bd244015b6e6 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java @@ -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 BODY_ONLY_FLAG = EnumSet.of(Flags.BODY_ONLY); private static final Set 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 state) throws CodegenException { + private void makeInsnBody(ICodeWriter code, InsnNode insn, Set 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 state, char op) throws CodegenException { + private void oneArgInsn(ICodeWriter code, InsnNode insn, Set 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 state) throws CodegenException { + private void makeTernary(TernaryInsn insn, ICodeWriter code, Set 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 state) throws CodegenException { + private void makeArith(ArithNode insn, ICodeWriter code, Set 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); diff --git a/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java b/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java index 3e5466d8a37b18508c81b8f218de231558085e53..52772c1978c47ed1decbd3a72e65282b9967b1be 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java @@ -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 args) { + private void addMethodArguments(ICodeWriter code, List args) { MethodParameters paramsAnnotation = mth.get(AType.ANNOTATION_MTH_PARAMETERS); int i = 0; Iterator 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(); diff --git a/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java b/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java index e6906d53d5c478d207e58786b1a327ee8c78bcfc..7a00a158f5afdc3d2f46f78baf33bdb7c535b738 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java @@ -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 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; diff --git a/jadx-core/src/main/java/jadx/core/codegen/json/JsonCodeGen.java b/jadx-core/src/main/java/jadx/core/codegen/json/JsonCodeGen.java index d5cc20519b7b3206f5412bf21ae3d36ea12c0fb9..4326c8159215f7a052a9ea772624097e66d96fbc 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/json/JsonCodeGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/json/JsonCodeGen.java @@ -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 lineMapping = code.getLineMapping(); Map annotations = code.getAnnotations(); long mthCodeOffset = mth.getMethodCodeOffset() + 16; diff --git a/jadx-core/src/main/java/jadx/core/dex/attributes/AttrList.java b/jadx-core/src/main/java/jadx/core/dex/attributes/AttrList.java index 86e18ffa46a00d9726d725027991f04725b816d9..4c982ac81f665f2d8dc0d31ead742c3ca56c4469 100644 --- a/jadx-core/src/main/java/jadx/core/dex/attributes/AttrList.java +++ b/jadx-core/src/main/java/jadx/core/dex/attributes/AttrList.java @@ -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 implements IAttribute { @@ -26,6 +26,6 @@ public class AttrList implements IAttribute { @Override public String toString() { - return Utils.listToString(list, CodeWriter.NL); + return Utils.listToString(list, ICodeWriter.NL); } } diff --git a/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/JadxError.java b/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/JadxError.java index 6b8667516262acd45b47d9217428707be0e078da..95338f26dd39e0107dbe4a896dc986465ea57b69 100644 --- a/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/JadxError.java +++ b/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/JadxError.java @@ -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 { @@ -59,7 +59,7 @@ public class JadxError implements Comparable { 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(); diff --git a/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/LocalVarsDebugInfoAttr.java b/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/LocalVarsDebugInfoAttr.java index a62dbcad4bdfff0921841ed4cb3cbdd02cbf7561..60380e2a78a817b753cb03f75db5e8597cfa25b6 100644 --- a/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/LocalVarsDebugInfoAttr.java +++ b/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/LocalVarsDebugInfoAttr.java @@ -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 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 + " "); } } diff --git a/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/PhiListAttr.java b/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/PhiListAttr.java index 41c61d7cf4940eb6892d3edd363a9c504b9e08d9..43e59cf5a51e360d647bd5c2d74898bfcf41a5b8 100644 --- a/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/PhiListAttr.java +++ b/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/PhiListAttr.java @@ -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(); } diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/SwitchInsn.java b/jadx-core/src/main/java/jadx/core/dex/instructions/SwitchInsn.java index 86db555ef9f6f662d2eeb85800a9db3bd44a3de8..f282392776d409c96b448c8c3a9accc5d40e825a 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/SwitchInsn.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/SwitchInsn.java @@ -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)); } } diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/InsnNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/InsnNode.java index f0e5f2370b901e41351e3e6ec62f7cdbb2e086ec..185d459c67356d1da419f41fc30c936fffd06ead 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/InsnNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/InsnNode.java @@ -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); } } diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java index 6cfb6286f2d81ced20c13ac4a2356044d71c4df0..78ab9ab0cbc972601ff28357c86abbf83e9cf19e 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java @@ -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; } diff --git a/jadx-core/src/main/java/jadx/core/dex/regions/SwitchRegion.java b/jadx-core/src/main/java/jadx/core/dex/regions/SwitchRegion.java index 482f40495b1bd8f674b21c52bcff052f59cc460b..c303fdaf1ffb3eed9b320f8f530f39da33c7d8d2 100644 --- a/jadx-core/src/main/java/jadx/core/dex/regions/SwitchRegion.java +++ b/jadx-core/src/main/java/jadx/core/dex/regions/SwitchRegion.java @@ -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 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()); } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java index ed69bc25f0956253c22189a6251cf948c8eee7a4..9fcdf76958e5e4219bfa544ea6c89ad2934251ba 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java @@ -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 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); } } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/MethodInvokeVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/MethodInvokeVisitor.java index e4428469baf0aa94a9c3a7eb79369970d8430c08..a7485d06dc765b128390ada8b7fff4ab9a97b283 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/MethodInvokeVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/MethodInvokeVisitor.java @@ -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(); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/debuginfo/DebugInfoAttachVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/debuginfo/DebugInfoAttachVisitor.java index 8e129500114e9134f30439653f61d8628498dd3e..910003f662b1a4e26d44cef8f79cf794ae52fac2 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/debuginfo/DebugInfoAttachVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/debuginfo/DebugInfoAttachVisitor.java @@ -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)); } } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/CheckRegions.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/CheckRegions.java index 39efecbd7dfcf2bbce778b4e1dbd7b40abc9f2f5..ec7c6143b3ddd5e3f042a811bce67081f9385ff4 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/CheckRegions.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/CheckRegions.java @@ -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(); } } diff --git a/jadx-core/src/main/java/jadx/core/utils/CodeGenUtils.java b/jadx-core/src/main/java/jadx/core/utils/CodeGenUtils.java index acc0c7747eddcfbc349a7bdd94e6c444abe511c2..042c3e0ad12397344f86d38e85403d56745fb5b0 100644 --- a/jadx-core/src/main/java/jadx/core/utils/CodeGenUtils.java +++ b/jadx-core/src/main/java/jadx/core/utils/CodeGenUtils.java @@ -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 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(" */"); diff --git a/jadx-core/src/main/java/jadx/core/utils/DebugChecks.java b/jadx-core/src/main/java/jadx/core/utils/DebugChecks.java index 8ac056721414347fa3a8f683358c8236c70ea3e7..91cb2a825a8a7a3e32ee267b83a7eae1b461f803 100644 --- a/jadx-core/src/main/java/jadx/core/utils/DebugChecks.java +++ b/jadx-core/src/main/java/jadx/core/utils/DebugChecks.java @@ -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); } } } diff --git a/jadx-core/src/main/java/jadx/core/utils/DebugUtils.java b/jadx-core/src/main/java/jadx/core/utils/DebugUtils.java index 29749e3400faea123abdf204625ec168f70c095b..df9faef4596a9994884c6c4d132096321e1de572 100644 --- a/jadx-core/src/main/java/jadx/core/utils/DebugUtils.java +++ b/jadx-core/src/main/java/jadx/core/utils/DebugUtils.java @@ -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 insnStrings = Stream.of(codeStr.split(NL)) + List 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 attrStrings = Stream.of(str.split(NL)) + List attrStrings = Stream.of(str.split(ICodeWriter.NL)) .filter(StringUtils::notBlank) .collect(Collectors.toList()); Iterator it = attrStrings.iterator(); diff --git a/jadx-core/src/main/java/jadx/core/utils/InsnRemover.java b/jadx-core/src/main/java/jadx/core/utils/InsnRemover.java index 386d6100d37c00dde2494a7f3ed6b81ff0d3259f..d14d5cfa0b39cb870652e7760998e7ab2ee528cf 100644 --- a/jadx-core/src/main/java/jadx/core/utils/InsnRemover.java +++ b/jadx-core/src/main/java/jadx/core/utils/InsnRemover.java @@ -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 + " ")); } } } diff --git a/jadx-core/src/main/java/jadx/core/utils/Utils.java b/jadx-core/src/main/java/jadx/core/utils/Utils.java index 43c1040bd7c7a87e843a3348ee5936dfc8ed1970..d8bdb2513fae3c44ef2697514f606d5be6dd3ab5 100644 --- a/jadx-core/src/main/java/jadx/core/utils/Utils.java +++ b/jadx-core/src/main/java/jadx/core/utils/Utils.java @@ -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; } diff --git a/jadx-core/src/main/java/jadx/core/utils/android/AndroidResourcesUtils.java b/jadx-core/src/main/java/jadx/core/utils/android/AndroidResourcesUtils.java index 2ba5d9f10a4d71cd1b1ac6c89a545b66bce6a8ed..21af1be632a9dd42424e2f0922b33aed211b5fb8 100644 --- a/jadx-core/src/main/java/jadx/core/utils/android/AndroidResourcesUtils.java +++ b/jadx-core/src/main/java/jadx/core/utils/android/AndroidResourcesUtils.java @@ -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); diff --git a/jadx-core/src/main/java/jadx/core/utils/exceptions/JadxRuntimeException.java b/jadx-core/src/main/java/jadx/core/utils/exceptions/JadxRuntimeException.java index eb56d010c397a3e145f06d8e2f757c0492ac5a09..69d8b0e6c2c401cd2df797d71abe7da47d8dce5b 100644 --- a/jadx-core/src/main/java/jadx/core/utils/exceptions/JadxRuntimeException.java +++ b/jadx-core/src/main/java/jadx/core/utils/exceptions/JadxRuntimeException.java @@ -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) { diff --git a/jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java b/jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java index 0443b6247b3f484d15971ae0874ba12111933ab1..bcd1b81d909df6553f389481af68c6b4ec16d6bc 100644 --- a/jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java +++ b/jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java @@ -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 nsMapGenerated; private final Map 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(""); 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; } diff --git a/jadx-core/src/main/java/jadx/core/xmlgen/ResTableParser.java b/jadx-core/src/main/java/jadx/core/xmlgen/ResTableParser.java index e34089ec6f0b08b74b13c410da983f8fb9bfa7dc..1d2075c10673b7483fd22dd684c80a71b22d64a5 100644 --- a/jadx-core/src/main/java/jadx/core/xmlgen/ResTableParser.java +++ b/jadx-core/src/main/java/jadx/core/xmlgen/ResTableParser.java @@ -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(""); writer.startLine(""); writer.incIndent(); diff --git a/jadx-core/src/main/java/jadx/core/xmlgen/ResXmlGen.java b/jadx-core/src/main/java/jadx/core/xmlgen/ResXmlGen.java index a8fb1bddcc214c3a1cdcac9e1c81286e6627feb8..ada5106c42913c9f625c4f161573e25029528dc3 100644 --- a/jadx-core/src/main/java/jadx/core/xmlgen/ResXmlGen.java +++ b/jadx-core/src/main/java/jadx/core/xmlgen/ResXmlGen.java @@ -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 makeResourcesXml() { - Map contMap = new HashMap<>(); + Map 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(""); cw.startLine(""); cw.incIndent(); @@ -53,10 +54,9 @@ public class ResXmlGen { } List files = new ArrayList<>(contMap.size()); - for (Map.Entry entry : contMap.entrySet()) { + for (Map.Entry entry : contMap.entrySet()) { String fileName = entry.getKey(); - CodeWriter content = entry.getValue(); - + ICodeWriter content = entry.getValue(); content.decIndent(); content.startLine(""); 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; } diff --git a/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java b/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java index 539e2120c415e5d2cdd15e329542b62e041b0cf0..a6ff59891ce8d1c02f1601c7ee7c1929517d7b00 100644 --- a/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java +++ b/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java @@ -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 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; diff --git a/jadx-core/src/test/java/jadx/tests/api/utils/JadxMatchers.java b/jadx-core/src/test/java/jadx/tests/api/utils/JadxMatchers.java index a67b60c1ce759f983a376d405081c1fd95b4df0d..c5e7409fb83d909146bc865ed3ba390a82905553 100644 --- a/jadx-core/src/test/java/jadx/tests/api/utils/JadxMatchers.java +++ b/jadx-core/src/test/java/jadx/tests/api/utils/JadxMatchers.java @@ -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 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()); } diff --git a/jadx-core/src/test/java/jadx/tests/api/utils/TestUtils.java b/jadx-core/src/test/java/jadx/tests/api/utils/TestUtils.java index 1182238c2c79175f0c7a60493bfb5beaff92fe33..21cee99c9587587ed28bc86e7e7af192dba431d6 100644 --- a/jadx-core/src/test/java/jadx/tests/api/utils/TestUtils.java +++ b/jadx-core/src/test/java/jadx/tests/api/utils/TestUtils.java @@ -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(); } diff --git a/jadx-core/src/test/java/jadx/tests/api/utils/assertj/JadxCodeAssertions.java b/jadx-core/src/test/java/jadx/tests/api/utils/assertj/JadxCodeAssertions.java index 2c5c75baea68b0ae563d7f807d4b754ccb6da669..b0872b4cf2266df5d0ba76a1171941290106350f 100644 --- a/jadx-core/src/test/java/jadx/tests/api/utils/assertj/JadxCodeAssertions.java +++ b/jadx-core/src/test/java/jadx/tests/api/utils/assertj/JadxCodeAssertions.java @@ -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 { @@ -52,7 +52,7 @@ public class JadxCodeAssertions extends AbstractStringAssert if (first) { first = false; } else { - sb.append(CodeWriter.NL); + sb.append(ICodeWriter.NL); } sb.append(indent); sb.append(line); diff --git a/jadx-core/src/test/java/jadx/tests/external/BaseExternalTest.java b/jadx-core/src/test/java/jadx/tests/external/BaseExternalTest.java index 1cd7c843be792f3bec39dd9c9febab8981de8e21..56cbc1cb1fb4c5b0ddfcb210df7a8bfbdf88d2be 100644 --- a/jadx-core/src/test/java/jadx/tests/external/BaseExternalTest.java +++ b/jadx-core/src/test/java/jadx/tests/external/BaseExternalTest.java @@ -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 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; } } diff --git a/jadx-core/src/test/java/jadx/tests/integration/debuginfo/TestLineNumbers.java b/jadx-core/src/test/java/jadx/tests/integration/debuginfo/TestLineNumbers.java index 703fccdfcec086b95a18d5d30c7ed309d197249b..454d880750ec51b33f5aa899ce0fbdf47998abf4 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/debuginfo/TestLineNumbers.java +++ b/jadx-core/src/test/java/jadx/tests/integration/debuginfo/TestLineNumbers.java @@ -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 {"); diff --git a/jadx-core/src/test/java/jadx/tests/integration/debuginfo/TestReturnSourceLine.java b/jadx-core/src/test/java/jadx/tests/integration/debuginfo/TestReturnSourceLine.java index 76f4217760a89be936409f2e7a8e71bfdbac0d84..58b064c8238846475a5da1da3c6e400e593c2500 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/debuginfo/TestReturnSourceLine.java +++ b/jadx-core/src/test/java/jadx/tests/integration/debuginfo/TestReturnSourceLine.java @@ -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;"); diff --git a/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java b/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java index c70a329f412d5c69ac54b6d9548aadce9845b36e..d59038d55179267fc328a3c2b66dad0ea35b8583 100644 --- a/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java +++ b/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java @@ -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; diff --git a/jadx-gui/src/main/java/jadx/gui/jobs/IndexJob.java b/jadx-gui/src/main/java/jadx/gui/jobs/IndexJob.java index 307facfc7b331f92bfaa9da849ea2f62476c4841..323b31b0acaaecef2d8e1455ba75517fad9fc546 100644 --- a/jadx-gui/src/main/java/jadx/gui/jobs/IndexJob.java +++ b/jadx-gui/src/main/java/jadx/gui/jobs/IndexJob.java @@ -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 splitLines(JavaClass cls) { - List lines = StringRef.split(cls.getCode(), CodeWriter.NL); + List 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()); diff --git a/jadx-gui/src/main/java/jadx/gui/treemodel/JResource.java b/jadx-gui/src/main/java/jadx/gui/treemodel/JResource.java index 761ecd6d33c5fc477460bfce095fc37655cd3690..b7dab37d360c1e43ebc9ae3885537eaa1aeeeed9 100644 --- a/jadx-gui/src/main/java/jadx/gui/treemodel/JResource.java +++ b/jadx-gui/src/main/java/jadx/gui/treemodel/JResource.java @@ -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 { private static final long serialVersionUID = -201018424302612434L; @@ -154,7 +153,7 @@ public class JResource extends JLoadableNode implements Comparable { 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: diff --git a/jadx-gui/src/main/java/jadx/gui/ui/ImagePanel.java b/jadx-gui/src/main/java/jadx/gui/ui/ImagePanel.java index 7693d3a121ddab508dd323e9ffc228edc65fb169..e50e87d6dba3b65ad5b8e31527dcee353c0302b4 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/ImagePanel.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/ImagePanel.java @@ -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); } } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/RenameDialog.java b/jadx-gui/src/main/java/jadx/gui/ui/RenameDialog.java index cc69da8dc31fb7fe6c4a323a716d023e7f1a0994..3e5b9d4dfd08af24e555db13364e0a5324d07e8d 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/RenameDialog.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/RenameDialog.java @@ -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) { diff --git a/jadx-gui/src/main/java/jadx/gui/utils/search/ResourceIndex.java b/jadx-gui/src/main/java/jadx/gui/utils/search/ResourceIndex.java index a04c2fd9206216dacb0fb86437ef53a3b282a2cc..9bdded3f028ae285a212f5357b8c93c95af3171f 100644 --- a/jadx-gui/src/main/java/jadx/gui/utils/search/ResourceIndex.java +++ b/jadx-gui/src/main/java/jadx/gui/utils/search/ResourceIndex.java @@ -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(); } } diff --git a/jadx-gui/src/main/java/jadx/gui/utils/search/TextSearchIndex.java b/jadx-gui/src/main/java/jadx/gui/utils/search/TextSearchIndex.java index 197b7d49fe7c9b0553009b920211243d9b7ab828..96098971139eb6aa09d51c4e7e3371c4f125a747 100644 --- a/jadx-gui/src/main/java/jadx/gui/utils/search/TextSearchIndex.java +++ b/jadx-gui/src/main/java/jadx/gui/utils/search/TextSearchIndex.java @@ -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 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;