├── .gitignore
├── .idea
├── vcs.xml
├── .gitignore
├── misc.xml
├── compiler.xml
└── jarRepositories.xml
├── README.md
├── src
├── main
│ └── java
│ │ └── org
│ │ └── jetbrains
│ │ └── java
│ │ └── decompiler
│ │ ├── ClassNameConstants.java
│ │ ├── struct
│ │ ├── gen
│ │ │ ├── NewClassNameBuilder.java
│ │ │ ├── generics
│ │ │ │ ├── GenericFieldDescriptor.java
│ │ │ │ ├── GenericClassDescriptor.java
│ │ │ │ └── GenericMethodDescriptor.java
│ │ │ ├── Type.java
│ │ │ ├── FieldDescriptor.java
│ │ │ ├── DataPoint.java
│ │ │ └── MethodDescriptor.java
│ │ ├── IDecompiledData.java
│ │ ├── consts
│ │ │ ├── PooledConstant.java
│ │ │ ├── PrimitiveConstant.java
│ │ │ └── LinkConstant.java
│ │ ├── attr
│ │ │ ├── StructConstantValueAttribute.java
│ │ │ ├── StructGenericSignatureAttribute.java
│ │ │ ├── StructAnnDefaultAttribute.java
│ │ │ ├── StructPermittedSubclassesAttribute.java
│ │ │ ├── StructExceptionsAttribute.java
│ │ │ ├── StructLocalVariableTypeTableAttribute.java
│ │ │ ├── StructAnnotationParameterAttribute.java
│ │ │ ├── StructEnclosingMethodAttribute.java
│ │ │ ├── StructRecordAttribute.java
│ │ │ ├── StructCodeAttribute.java
│ │ │ ├── StructLineNumberTableAttribute.java
│ │ │ ├── StructMethodParametersAttribute.java
│ │ │ ├── StructBootstrapMethodsAttribute.java
│ │ │ ├── StructInnerClassesAttribute.java
│ │ │ ├── StructLocalVariableTableAttribute.java
│ │ │ └── StructTypeAnnotationAttribute.java
│ │ ├── match
│ │ │ ├── IMatchable.java
│ │ │ └── MatchNode.java
│ │ ├── StructRecordComponent.java
│ │ ├── StructTypePathEntry.java
│ │ ├── StructField.java
│ │ └── lazy
│ │ │ └── LazyLoader.java
│ │ ├── main
│ │ ├── extern
│ │ │ ├── IBytecodeProvider.java
│ │ │ ├── ClassFormatException.java
│ │ │ ├── IIdentifierRenamer.java
│ │ │ ├── IResultSaver.java
│ │ │ ├── IFernflowerLogger.java
│ │ │ └── IFernflowerPreferences.java
│ │ ├── collectors
│ │ │ ├── CounterContainer.java
│ │ │ ├── VarNamesCollector.java
│ │ │ ├── BytecodeMappingTracer.java
│ │ │ └── BytecodeSourceMapper.java
│ │ ├── decompiler
│ │ │ ├── shxjia
│ │ │ │ ├── CustomeBytecodeProvider.java
│ │ │ │ └── CustomeResultSaver.java
│ │ │ ├── BaseDecompiler.java
│ │ │ └── PrintStreamLogger.java
│ │ ├── rels
│ │ │ └── MethodWrapper.java
│ │ ├── EnumProcessor.java
│ │ └── Fernflower.java
│ │ ├── modules
│ │ ├── decompiler
│ │ │ ├── decompose
│ │ │ │ ├── IGraphNode.java
│ │ │ │ ├── IGraph.java
│ │ │ │ ├── DominatorEngine.java
│ │ │ │ └── GenericDominatorEngine.java
│ │ │ ├── ExpressionStack.java
│ │ │ ├── ExprentStack.java
│ │ │ ├── ClearStructHelper.java
│ │ │ ├── stats
│ │ │ │ ├── DummyExitStatement.java
│ │ │ │ ├── RootStatement.java
│ │ │ │ ├── Statements.java
│ │ │ │ ├── GeneralStatement.java
│ │ │ │ ├── BasicBlockStatement.java
│ │ │ │ └── SequenceStatement.java
│ │ │ ├── PrimitiveExpressionList.java
│ │ │ ├── PrimitiveExprsList.java
│ │ │ ├── exps
│ │ │ │ ├── AssertExprent.java
│ │ │ │ ├── TypeAnnotation.java
│ │ │ │ ├── MonitorExprent.java
│ │ │ │ ├── ExprUtil.java
│ │ │ │ ├── AnnotationExprent.java
│ │ │ │ ├── SwitchExprent.java
│ │ │ │ ├── ArrayExprent.java
│ │ │ │ └── IfExprent.java
│ │ │ ├── vars
│ │ │ │ ├── VarVersionEdge.java
│ │ │ │ ├── VarVersionPair.java
│ │ │ │ ├── CheckTypesResult.java
│ │ │ │ ├── VarVersionNode.java
│ │ │ │ └── VarVersionsGraph.java
│ │ │ ├── sforms
│ │ │ │ ├── DirectNode.java
│ │ │ │ └── DirectGraph.java
│ │ │ ├── typeann
│ │ │ │ ├── TypeAnnotationWriteHelper.java
│ │ │ │ └── TypeAnnotation.java
│ │ │ ├── ClasspathHelper.java
│ │ │ ├── StrongConnectivityHelper.java
│ │ │ └── PPandMMHelper.java
│ │ └── renamer
│ │ │ ├── PoolInterceptor.java
│ │ │ └── ClassWrapperNode.java
│ │ ├── code
│ │ ├── ExceptionTable.java
│ │ ├── SimpleInstructionSequence.java
│ │ ├── JumpInstruction.java
│ │ ├── ExceptionHandler.java
│ │ ├── FullInstructionSequence.java
│ │ ├── SwitchInstruction.java
│ │ ├── cfg
│ │ │ └── ExceptionRangeCFG.java
│ │ ├── Instruction.java
│ │ └── InstructionSequence.java
│ │ └── util
│ │ ├── DataInputFullStream.java
│ │ ├── ListStack.java
│ │ ├── InterpreterUtil.java
│ │ ├── FilterClass.java
│ │ └── VBStyleCollection.java
└── test
│ └── java
│ └── Test.java
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | # Project exclude paths
2 | /target/
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # fernflower
2 | wocao
3 | gansha?
4 |
5 |
6 | https://github.com/fesh0r/fernflower
7 | https://github.com/fesh0r/fernflower
8 | https://github.com/fesh0r/fernflower
9 | https://github.com/fesh0r/fernflower
10 | https://github.com/fesh0r/fernflower
11 | 说5遍
12 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 | # Zeppelin ignored files
10 | /ZeppelinRemoteNotebooks/
11 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/ClassNameConstants.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
2 | package org.jetbrains.java.decompiler;
3 |
4 | public interface ClassNameConstants {
5 | String JAVA_LANG_STRING = "java/lang/String";
6 | }
7 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/gen/NewClassNameBuilder.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.gen;
3 |
4 | public interface NewClassNameBuilder {
5 | String buildNewClassname(String className);
6 | }
7 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/IDecompiledData.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct;
3 |
4 | public interface IDecompiledData {
5 |
6 | String getClassEntryName(StructClass cl, String entryname);
7 |
8 | String getClassContent(StructClass cl);
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/main/extern/IBytecodeProvider.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.main.extern;
3 |
4 | import java.io.IOException;
5 |
6 | public interface IBytecodeProvider {
7 | byte[] getBytecode(String externalPath, String internalPath) throws IOException;
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/decompose/IGraphNode.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler.decompose;
3 |
4 | import java.util.List;
5 |
6 | public interface IGraphNode {
7 | List extends IGraphNode> getPredecessorNodes();
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/main/extern/ClassFormatException.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.main.extern;
3 |
4 | public class ClassFormatException extends RuntimeException {
5 | public ClassFormatException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/gen/generics/GenericFieldDescriptor.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.gen.generics;
3 |
4 | public class GenericFieldDescriptor {
5 | public final GenericType type;
6 |
7 | public GenericFieldDescriptor(GenericType type) {
8 | this.type = type;
9 | }
10 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/decompose/IGraph.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler.decompose;
3 |
4 | import java.util.List;
5 | import java.util.Set;
6 |
7 | public interface IGraph {
8 |
9 | List extends IGraphNode> getReversePostOrderList();
10 |
11 | Set extends IGraphNode> getRoots();
12 | }
13 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/consts/PooledConstant.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.consts;
3 |
4 | import org.jetbrains.java.decompiler.code.CodeConstants;
5 |
6 | public class PooledConstant implements CodeConstants {
7 | public final int type;
8 |
9 | public PooledConstant(int type) {
10 | this.type = type;
11 | }
12 |
13 | public void resolveConstant(ConstantPool pool) { }
14 | }
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/gen/generics/GenericClassDescriptor.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.gen.generics;
3 |
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | public class GenericClassDescriptor {
8 |
9 | public GenericType superclass;
10 |
11 | public final List superinterfaces = new ArrayList<>();
12 |
13 | public final List fparameters = new ArrayList<>();
14 |
15 | public final List> fbounds = new ArrayList<>();
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/code/ExceptionTable.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.code;
3 |
4 | import java.util.Collections;
5 | import java.util.List;
6 |
7 | public class ExceptionTable {
8 | public static final ExceptionTable EMPTY = new ExceptionTable(Collections.emptyList());
9 |
10 | private final List handlers;
11 |
12 | public ExceptionTable(List handlers) {
13 | this.handlers = handlers;
14 | }
15 |
16 | public List getHandlers() {
17 | return handlers;
18 | }
19 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/main/extern/IIdentifierRenamer.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.main.extern;
3 |
4 | public interface IIdentifierRenamer {
5 |
6 | enum Type {ELEMENT_CLASS, ELEMENT_FIELD, ELEMENT_METHOD}
7 |
8 | boolean toBeRenamed(Type elementType, String className, String element, String descriptor);
9 |
10 | String getNextClassName(String fullName, String shortName);
11 |
12 | String getNextFieldName(String className, String field, String descriptor);
13 |
14 | String getNextMethodName(String className, String method, String descriptor);
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/util/DataInputFullStream.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.util;
3 |
4 | import java.io.ByteArrayInputStream;
5 | import java.io.DataInputStream;
6 | import java.io.IOException;
7 |
8 | public class DataInputFullStream extends DataInputStream {
9 | public DataInputFullStream(byte[] bytes) {
10 | super(new ByteArrayInputStream(bytes));
11 | }
12 |
13 | public byte[] read(int n) throws IOException {
14 | return InterpreterUtil.readBytes(this, n);
15 | }
16 |
17 | public void discard(int n) throws IOException {
18 | InterpreterUtil.discardBytes(this, n);
19 | }
20 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/attr/StructConstantValueAttribute.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.attr;
3 |
4 | import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
5 | import org.jetbrains.java.decompiler.util.DataInputFullStream;
6 |
7 | import java.io.IOException;
8 |
9 | public class StructConstantValueAttribute extends StructGeneralAttribute {
10 |
11 | private int index;
12 |
13 | @Override
14 | public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException {
15 | index = data.readUnsignedShort();
16 | }
17 |
18 | public int getIndex() {
19 | return index;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/main/collectors/CounterContainer.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.main.collectors;
3 |
4 | public class CounterContainer {
5 | public static final int STATEMENT_COUNTER = 0;
6 | public static final int EXPRESSION_COUNTER = 1;
7 | public static final int VAR_COUNTER = 2;
8 |
9 | private final int[] values = new int[]{1, 1, 1};
10 |
11 | public void setCounter(int counter, int value) {
12 | values[counter] = value;
13 | }
14 |
15 | public int getCounter(int counter) {
16 | return values[counter];
17 | }
18 |
19 | public int getCounterAndIncrement(int counter) {
20 | return values[counter]++;
21 | }
22 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/ExpressionStack.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler;
3 |
4 | import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
5 | import org.jetbrains.java.decompiler.util.ListStack;
6 |
7 | public class ExpressionStack extends ListStack {
8 | public ExpressionStack() { }
9 |
10 | private ExpressionStack(int initialCapacity) {
11 | super(initialCapacity);
12 | }
13 |
14 | @Override
15 | public ExpressionStack copy() {
16 | ExpressionStack copy = new ExpressionStack(size());
17 | for (Exprent expr : this) copy.push(expr.copy());
18 | return copy;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/code/SimpleInstructionSequence.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.code;
3 |
4 | import org.jetbrains.java.decompiler.util.VBStyleCollection;
5 |
6 | public class SimpleInstructionSequence extends InstructionSequence {
7 |
8 | public SimpleInstructionSequence() {
9 | }
10 |
11 | public SimpleInstructionSequence(VBStyleCollection collinstr) {
12 | super(collinstr);
13 | }
14 |
15 | @Override
16 | public SimpleInstructionSequence clone() {
17 | SimpleInstructionSequence newseq = new SimpleInstructionSequence(collinstr.clone());
18 | newseq.setPointer(this.getPointer());
19 |
20 | return newseq;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/ExprentStack.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler;
3 |
4 | import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
5 | import org.jetbrains.java.decompiler.util.ListStack;
6 |
7 | public class ExprentStack extends ListStack {
8 |
9 | public ExprentStack() {
10 | }
11 |
12 | public ExprentStack(ListStack list) {
13 | super(list);
14 | pointer = list.getPointer();
15 | }
16 |
17 | @Override
18 | public Exprent pop() {
19 |
20 | return this.remove(--pointer);
21 | }
22 |
23 | @Override
24 | public ExprentStack clone() {
25 | return new ExprentStack(this);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/code/JumpInstruction.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.code;
3 |
4 | public class JumpInstruction extends Instruction {
5 | public int destination;
6 |
7 | public JumpInstruction(int opcode, int group, boolean wide, int bytecodeVersion, int[] operands) {
8 | super(opcode, group, wide, bytecodeVersion, operands);
9 | }
10 |
11 | @Override
12 | public void initInstruction(InstructionSequence seq) {
13 | destination = seq.getPointerByRelOffset(this.operand(0));
14 | }
15 |
16 | @Override
17 | public JumpInstruction clone() {
18 | JumpInstruction copy = (JumpInstruction)super.clone();
19 | copy.destination = destination;
20 | return copy;
21 | }
22 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/ClearStructHelper.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler;
3 |
4 | import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
5 | import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
6 |
7 | import java.util.LinkedList;
8 |
9 |
10 | public final class ClearStructHelper {
11 |
12 | public static void clearStatements(RootStatement root) {
13 |
14 | LinkedList stack = new LinkedList<>();
15 | stack.add(root);
16 |
17 | while (!stack.isEmpty()) {
18 |
19 | Statement stat = stack.removeFirst();
20 |
21 | stat.clearTempInformation();
22 |
23 | stack.addAll(stat.getStats());
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/attr/StructGenericSignatureAttribute.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.attr;
3 |
4 | import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
5 | import org.jetbrains.java.decompiler.util.DataInputFullStream;
6 |
7 | import java.io.IOException;
8 |
9 | public class StructGenericSignatureAttribute extends StructGeneralAttribute {
10 |
11 | private String signature;
12 |
13 | @Override
14 | public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException {
15 | int index = data.readUnsignedShort();
16 | signature = pool.getPrimitiveConstant(index).getString();
17 | }
18 |
19 | public String getSignature() {
20 | return signature;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/renamer/PoolInterceptor.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.renamer;
3 |
4 | import java.util.HashMap;
5 | import java.util.Map;
6 |
7 | public class PoolInterceptor {
8 | private final Map mapOldToNewNames = new HashMap<>();
9 | private final Map mapNewToOldNames = new HashMap<>();
10 |
11 | public void addName(String oldName, String newName) {
12 | mapOldToNewNames.put(oldName, newName);
13 | mapNewToOldNames.put(newName, oldName);
14 | }
15 |
16 | public String getName(String oldName) {
17 | return mapOldToNewNames.get(oldName);
18 | }
19 |
20 | public String getOldName(String newName) {
21 | return mapNewToOldNames.get(newName);
22 | }
23 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/renamer/ClassWrapperNode.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.renamer;
3 |
4 | import org.jetbrains.java.decompiler.struct.StructClass;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | public class ClassWrapperNode {
10 | private final StructClass classStruct;
11 | private final List subclasses = new ArrayList<>();
12 |
13 | public ClassWrapperNode(StructClass cl) {
14 | this.classStruct = cl;
15 | }
16 |
17 | public void addSubclass(ClassWrapperNode node) {
18 | subclasses.add(node);
19 | }
20 |
21 | public StructClass getClassStruct() {
22 | return classStruct;
23 | }
24 |
25 | public List getSubclasses() {
26 | return subclasses;
27 | }
28 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/attr/StructAnnDefaultAttribute.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.attr;
3 |
4 | import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
5 | import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
6 | import org.jetbrains.java.decompiler.util.DataInputFullStream;
7 |
8 | import java.io.IOException;
9 |
10 | public class StructAnnDefaultAttribute extends StructGeneralAttribute {
11 |
12 | private Exprent defaultValue;
13 |
14 | @Override
15 | public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException {
16 | defaultValue = StructAnnotationAttribute.parseAnnotationElement(data, pool);
17 | }
18 |
19 | public Exprent getDefaultValue() {
20 | return defaultValue;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/match/IMatchable.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.match;
3 |
4 | public interface IMatchable {
5 | enum MatchProperties {
6 | STATEMENT_TYPE,
7 | STATEMENT_RET,
8 | STATEMENT_STATSIZE,
9 | STATEMENT_EXPRSIZE,
10 | STATEMENT_POSITION,
11 | STATEMENT_IFTYPE,
12 |
13 | EXPRENT_TYPE,
14 | EXPRENT_RET,
15 | EXPRENT_POSITION,
16 | EXPRENT_FUNCTYPE,
17 | EXPRENT_EXITTYPE,
18 | EXPRENT_CONSTTYPE,
19 | EXPRENT_CONSTVALUE,
20 | EXPRENT_INVOCATION_CLASS,
21 | EXPRENT_INVOCATION_SIGNATURE,
22 | EXPRENT_INVOCATION_PARAMETER,
23 | EXPRENT_VAR_INDEX,
24 | EXPRENT_FIELD_NAME,
25 | }
26 |
27 | IMatchable findObject(MatchNode matchNode, int index);
28 |
29 | boolean match(MatchNode matchNode, MatchEngine engine);
30 | }
--------------------------------------------------------------------------------
/src/test/java/Test.java:
--------------------------------------------------------------------------------
1 | import java.util.concurrent.*;
2 |
3 | public class Test {
4 | public static void main(String[] args) throws Exception {
5 | ExecutorService executorService = Executors.newSingleThreadExecutor();
6 | for(int a=0;a<10;a++){
7 | functionTimeoutTest2(executorService);
8 | }
9 | executorService.shutdown();
10 |
11 | }
12 |
13 | public static void functionTimeoutTest2(ExecutorService executorService) throws Exception {
14 |
15 | Future future = executorService.submit(() -> {
16 | Thread.sleep(1000);
17 | return "success";
18 | });
19 | try {
20 | String result = future.get(5, TimeUnit.SECONDS);
21 | System.out.println("result:" + result);
22 | return;
23 | } catch (TimeoutException e) {
24 | System.out.println("超时了!");
25 | return;
26 | }
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/DummyExitStatement.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler.stats;
3 |
4 | import java.util.Collection;
5 | import java.util.HashSet;
6 | import java.util.Set;
7 |
8 | public class DummyExitStatement extends Statement {
9 | public Set bytecode = null; // offsets of bytecode instructions mapped to dummy exit
10 |
11 | public DummyExitStatement() {
12 | super(StatementType.DUMMY_EXIT);
13 | }
14 |
15 | public void addBytecodeOffsets(Collection bytecodeOffsets) {
16 | if (bytecodeOffsets != null && !bytecodeOffsets.isEmpty()) {
17 | if (bytecode == null) {
18 | bytecode = new HashSet<>(bytecodeOffsets);
19 | }
20 | else {
21 | bytecode.addAll(bytecodeOffsets);
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/main/extern/IResultSaver.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.main.extern;
3 |
4 | import java.util.jar.Manifest;
5 |
6 | public interface IResultSaver {
7 | void saveFolder(String path);
8 |
9 | void copyFile(String source, String path, String entryName);
10 |
11 | void saveClassFile(String path, String qualifiedName, String entryName, String content, int[] mapping);
12 |
13 | void createArchive(String path, String archiveName, Manifest manifest);
14 |
15 | void saveDirEntry(String path, String archiveName, String entryName);
16 |
17 | void copyEntry(String source, String path, String archiveName, String entry);
18 |
19 | void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content);
20 |
21 | void closeArchive(String path, String archiveName);
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/code/ExceptionHandler.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.code;
3 |
4 | import org.jetbrains.java.decompiler.main.DecompilerContext;
5 |
6 | public class ExceptionHandler {
7 | public int from = 0;
8 | public int to = 0;
9 | public int handler = 0;
10 |
11 | public int from_instr = 0;
12 | public int to_instr = 0;
13 | public int handler_instr = 0;
14 |
15 | public String exceptionClass = null;
16 |
17 | public String toString() {
18 | String new_line_separator = DecompilerContext.getNewLineSeparator();
19 | return "from: " + from + " to: " + to + " handler: " + handler + new_line_separator +
20 | "from_instr: " + from_instr + " to_instr: " + to_instr + " handler_instr: " + handler_instr + new_line_separator +
21 | "exceptionClass: " + exceptionClass + new_line_separator;
22 | }
23 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/main/collectors/VarNamesCollector.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.main.collectors;
3 |
4 | import java.util.Collection;
5 | import java.util.HashSet;
6 | import java.util.Set;
7 |
8 | public class VarNamesCollector {
9 |
10 | private final Set usedNames = new HashSet<>();
11 |
12 | public VarNamesCollector() { }
13 |
14 | public VarNamesCollector(Collection setNames) {
15 | usedNames.addAll(setNames);
16 | }
17 |
18 | public void addName(String value) {
19 | usedNames.add(value);
20 | }
21 |
22 | public String getFreeName(int index) {
23 | return getFreeName("var" + index);
24 | }
25 |
26 | public String getFreeName(String proposition) {
27 | while (usedNames.contains(proposition)) {
28 | proposition += "x";
29 | }
30 | usedNames.add(proposition);
31 | return proposition;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/PrimitiveExpressionList.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler;
3 |
4 | import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | public class PrimitiveExpressionList {
10 | private final List expressions = new ArrayList<>();
11 | private final ExpressionStack stack;
12 |
13 | public PrimitiveExpressionList() {
14 | this(new ExpressionStack());
15 | }
16 |
17 | private PrimitiveExpressionList(ExpressionStack stack) {
18 | this.stack = stack;
19 | }
20 |
21 | public PrimitiveExpressionList copy() {
22 | return new PrimitiveExpressionList(stack.copy());
23 | }
24 |
25 | public List getExpressions() {
26 | return expressions;
27 | }
28 |
29 | public ExpressionStack getStack() {
30 | return stack;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/PrimitiveExprsList.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler;
3 |
4 | import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | public class PrimitiveExprsList {
10 |
11 | private final List lstExprents = new ArrayList<>();
12 |
13 | private ExprentStack stack = new ExprentStack();
14 |
15 | public PrimitiveExprsList() {
16 | }
17 |
18 | public PrimitiveExprsList copyStack() {
19 | PrimitiveExprsList prlst = new PrimitiveExprsList();
20 | prlst.setStack(stack.clone());
21 | return prlst;
22 | }
23 |
24 | public List getLstExprents() {
25 | return lstExprents;
26 | }
27 |
28 | public ExprentStack getStack() {
29 | return stack;
30 | }
31 |
32 | public void setStack(ExprentStack stack) {
33 | this.stack = stack;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/main/decompiler/shxjia/CustomeBytecodeProvider.java:
--------------------------------------------------------------------------------
1 | package org.jetbrains.java.decompiler.main.decompiler.shxjia;
2 |
3 | import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider;
4 | import org.jetbrains.java.decompiler.util.InterpreterUtil;
5 |
6 | import java.io.File;
7 | import java.io.IOException;
8 | import java.util.zip.ZipEntry;
9 | import java.util.zip.ZipFile;
10 |
11 | public class CustomeBytecodeProvider implements IBytecodeProvider {
12 | @Override
13 | public byte[] getBytecode(String externalPath, String internalPath) throws IOException {
14 | File file = new File(externalPath);
15 | if (internalPath == null) {
16 | return InterpreterUtil.getBytes(file);
17 | } else {
18 | try (ZipFile archive = new ZipFile(file)) {
19 | ZipEntry entry = archive.getEntry(internalPath);
20 | if (entry == null) throw new IOException("Entry not found: " + internalPath);
21 | return InterpreterUtil.getBytes(archive, entry);
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/code/FullInstructionSequence.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.code;
3 |
4 | import org.jetbrains.java.decompiler.util.VBStyleCollection;
5 |
6 |
7 | public class FullInstructionSequence extends InstructionSequence {
8 |
9 | // *****************************************************************************
10 | // constructors
11 | // *****************************************************************************
12 |
13 | public FullInstructionSequence(VBStyleCollection collinstr, ExceptionTable extable) {
14 | super(collinstr);
15 | this.exceptionTable = extable;
16 |
17 | // translate raw exception handlers to instr
18 | for (ExceptionHandler handler : extable.getHandlers()) {
19 | handler.from_instr = this.getPointerByAbsOffset(handler.from);
20 | handler.to_instr = this.getPointerByAbsOffset(handler.to);
21 | handler.handler_instr = this.getPointerByAbsOffset(handler.handler);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler.stats;
3 |
4 | import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
5 | import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
6 | import org.jetbrains.java.decompiler.util.TextBuffer;
7 |
8 | public class RootStatement extends Statement {
9 | private final DummyExitStatement dummyExit;
10 |
11 | public RootStatement(Statement head, DummyExitStatement dummyExit) {
12 | super(StatementType.ROOT);
13 |
14 | first = head;
15 | this.dummyExit = dummyExit;
16 |
17 | stats.addWithKey(first, first.id);
18 | first.setParent(this);
19 | }
20 |
21 | @Override
22 | public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
23 | return ExprProcessor.listToJava(varDefinitions, indent, tracer).append(first.toJava(indent, tracer));
24 | }
25 |
26 | public DummyExitStatement getDummyExit() {
27 | return dummyExit;
28 | }
29 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/gen/Type.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
2 | package org.jetbrains.java.decompiler.struct.gen;
3 |
4 | import org.jetbrains.java.decompiler.main.DecompilerContext;
5 | import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
6 |
7 | import java.util.Arrays;
8 | import java.util.List;
9 |
10 | public interface Type {
11 | int getType();
12 |
13 | int getArrayDim();
14 |
15 | String getValue();
16 |
17 | /**
18 | * Checks whether this Type can be annotated. Nested types can't be annotated when the right side of the currently considered types
19 | * contains a reference to a static class.
20 | */
21 | default boolean isAnnotatable() {
22 | List nestedTypes = Arrays.asList(DecompilerContext.getImportCollector().getNestedName(getValue()).split("\\."));
23 | if (nestedTypes.isEmpty()) return true;
24 | String curPath = getValue().substring(0, getValue().lastIndexOf('/') + 1) + nestedTypes.get(0) + '$';
25 | return ExprProcessor.canWriteNestedTypeAnnotation(curPath, nestedTypes.subList(1, nestedTypes.size()));
26 | }
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/main/decompiler/BaseDecompiler.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.main.decompiler;
3 |
4 | import org.jetbrains.java.decompiler.main.Fernflower;
5 | import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider;
6 | import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
7 | import org.jetbrains.java.decompiler.main.extern.IResultSaver;
8 |
9 | import java.io.File;
10 | import java.util.Map;
11 |
12 | @SuppressWarnings("unused")
13 | public class BaseDecompiler {
14 | private final Fernflower engine;
15 |
16 | public BaseDecompiler(IBytecodeProvider provider, IResultSaver saver, Map options, IFernflowerLogger logger) {
17 | engine = new Fernflower(provider, saver, options, logger);
18 | }
19 |
20 | public void addSource(File source) {
21 | engine.addSource(source);
22 | }
23 |
24 | public void addLibrary(File library) {
25 | engine.addLibrary(library);
26 | }
27 |
28 | public void decompileContext() {
29 | try {
30 | engine.decompileContext();
31 | }
32 | finally {
33 | engine.clearContext();
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/AssertExprent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
3 | */
4 | package org.jetbrains.java.decompiler.modules.decompiler.exps;
5 |
6 | import org.jetbrains.java.decompiler.util.TextBuffer;
7 | import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
8 |
9 | import java.util.List;
10 |
11 | public class AssertExprent extends Exprent {
12 |
13 | private final List extends Exprent> parameters;
14 |
15 | public AssertExprent(List extends Exprent> parameters) {
16 | super(EXPRENT_ASSERT);
17 | this.parameters = parameters;
18 | }
19 |
20 | @Override
21 | public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
22 | TextBuffer buffer = new TextBuffer();
23 |
24 | buffer.append("assert ");
25 |
26 | tracer.addMapping(bytecode);
27 |
28 | if (parameters.get(0) == null) {
29 | buffer.append("false");
30 | }
31 | else {
32 | buffer.append(parameters.get(0).toJava(indent, tracer));
33 | }
34 |
35 | if (parameters.size() > 1) {
36 | buffer.append(" : ");
37 | buffer.append(parameters.get(1).toJava(indent, tracer));
38 | }
39 |
40 | return buffer;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionEdge.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler.vars;
3 |
4 | public class VarVersionEdge { // FIXME: can be removed?
5 |
6 | public static final int EDGE_GENERAL = 0;
7 | public static final int EDGE_PHANTOM = 1;
8 |
9 | public final int type;
10 |
11 | public final VarVersionNode source;
12 |
13 | public final VarVersionNode dest;
14 |
15 | private final int hashCode;
16 |
17 | public VarVersionEdge(int type, VarVersionNode source, VarVersionNode dest) {
18 | this.type = type;
19 | this.source = source;
20 | this.dest = dest;
21 | this.hashCode = source.hashCode() ^ dest.hashCode() + type;
22 | }
23 |
24 | @Override
25 | public boolean equals(Object o) {
26 | if (o == this) return true;
27 | if (!(o instanceof VarVersionEdge edge)) return false;
28 |
29 | return type == edge.type && source == edge.source && dest == edge.dest;
30 | }
31 |
32 | @Override
33 | public int hashCode() {
34 | return hashCode;
35 | }
36 |
37 | @Override
38 | public String toString() {
39 | return source.toString() + " ->" + type + "-> " + dest.toString();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/attr/StructPermittedSubclassesAttribute.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.attr;
3 |
4 | import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
5 | import org.jetbrains.java.decompiler.util.DataInputFullStream;
6 |
7 | import java.io.IOException;
8 | import java.util.Arrays;
9 | import java.util.List;
10 |
11 | /*
12 | PermittedSubclasses_attribute {
13 | u2 attribute_name_index;
14 | u4 attribute_length;
15 | u2 number_of_classes;
16 | u2 classes[number_of_classes];
17 | }
18 | */
19 | public class StructPermittedSubclassesAttribute extends StructGeneralAttribute {
20 | List classes;
21 |
22 | @Override
23 | public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException {
24 | int numberOfClasses = data.readUnsignedShort();
25 | String[] classes = new String[numberOfClasses];
26 | for (int i = 0; i < numberOfClasses; i++) {
27 | classes[i] = pool.getPrimitiveConstant(data.readUnsignedShort()).getString();
28 | }
29 | this.classes = Arrays.asList(classes);
30 | }
31 |
32 | public List getClasses() {
33 | return classes;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/attr/StructExceptionsAttribute.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.attr;
3 |
4 | import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
5 | import org.jetbrains.java.decompiler.util.DataInputFullStream;
6 |
7 | import java.io.IOException;
8 | import java.util.ArrayList;
9 | import java.util.Collections;
10 | import java.util.List;
11 |
12 | public class StructExceptionsAttribute extends StructGeneralAttribute {
13 |
14 | private List throwsExceptions;
15 |
16 | @Override
17 | public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException {
18 | int len = data.readUnsignedShort();
19 | if (len > 0) {
20 | throwsExceptions = new ArrayList<>(len);
21 | for (int i = 0; i < len; i++) {
22 | throwsExceptions.add(data.readUnsignedShort());
23 | }
24 | }
25 | else {
26 | throwsExceptions = Collections.emptyList();
27 | }
28 | }
29 |
30 | public String getExcClassname(int index, ConstantPool pool) {
31 | return pool.getPrimitiveConstant(throwsExceptions.get(index)).getString();
32 | }
33 |
34 | public List getThrowsExceptions() {
35 | return throwsExceptions;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionPair.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler.vars;
3 |
4 | import org.jetbrains.java.decompiler.modules.decompiler.exps.VarExprent;
5 |
6 | public class VarVersionPair {
7 |
8 | public final int var;
9 | public final int version;
10 |
11 | private int hashCode = -1;
12 |
13 | public VarVersionPair(int var, int version) {
14 | this.var = var;
15 | this.version = version;
16 | }
17 |
18 | public VarVersionPair(Integer var, Integer version) {
19 | this.var = var;
20 | this.version = version;
21 | }
22 |
23 | public VarVersionPair(VarExprent var) {
24 | this.var = var.getIndex();
25 | this.version = var.getVersion();
26 | }
27 |
28 | @Override
29 | public boolean equals(Object o) {
30 | if (o == this) return true;
31 | if (!(o instanceof VarVersionPair paar)) return false;
32 |
33 | return var == paar.var && version == paar.version;
34 | }
35 |
36 | @Override
37 | public int hashCode() {
38 | if (hashCode == -1) {
39 | hashCode = this.var * 3 + this.version;
40 | }
41 | return hashCode;
42 | }
43 |
44 | @Override
45 | public String toString() {
46 | return "(" + var + "," + version + ")";
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/attr/StructLocalVariableTypeTableAttribute.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.attr;
3 |
4 | import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
5 | import org.jetbrains.java.decompiler.util.DataInputFullStream;
6 |
7 | import java.io.IOException;
8 |
9 | /*
10 | u2 local_variable_type_table_length;
11 | { u2 start_pc;
12 | u2 length;
13 | u2 name_index;
14 | u2 signature_index;
15 | u2 index;
16 | } local_variable_type_table[local_variable_type_table_length];
17 | */
18 | public class StructLocalVariableTypeTableAttribute extends StructGeneralAttribute {
19 | // store signature instead of descriptor
20 | private final StructLocalVariableTableAttribute backingAttribute = new StructLocalVariableTableAttribute();
21 |
22 | @Override
23 | public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException {
24 | backingAttribute.initContent(data, pool);
25 | }
26 |
27 | public void add(StructLocalVariableTypeTableAttribute attr) {
28 | backingAttribute.add(attr.backingAttribute);
29 | }
30 |
31 | public String getSignature(int index, int visibleOffset) {
32 | return backingAttribute.getDescriptor(index, visibleOffset);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/gen/generics/GenericMethodDescriptor.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.gen.generics;
3 |
4 | import java.util.Collections;
5 | import java.util.List;
6 |
7 | public class GenericMethodDescriptor {
8 | public final List typeParameters;
9 | public final List> typeParameterBounds;
10 | public final List parameterTypes;
11 | public final GenericType returnType;
12 | public final List exceptionTypes;
13 |
14 | public GenericMethodDescriptor(List typeParameters,
15 | List> typeParameterBounds,
16 | List parameterTypes,
17 | GenericType returnType,
18 | List exceptionTypes) {
19 | this.typeParameters = substitute(typeParameters);
20 | this.typeParameterBounds = substitute(typeParameterBounds);
21 | this.parameterTypes = substitute(parameterTypes);
22 | this.returnType = returnType;
23 | this.exceptionTypes = substitute(exceptionTypes);
24 | }
25 |
26 | private static List substitute(List list) {
27 | return list.isEmpty() ? Collections.emptyList() : list;
28 | }
29 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/vars/CheckTypesResult.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler.vars;
3 |
4 | import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
5 | import org.jetbrains.java.decompiler.struct.gen.VarType;
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | public class CheckTypesResult {
11 | private final List maxTypeExprents = new ArrayList<>();
12 | private final List minTypeExprents = new ArrayList<>();
13 |
14 | public void addMaxTypeExprent(Exprent exprent, VarType type) {
15 | maxTypeExprents.add(new ExprentTypePair(exprent, type));
16 | }
17 |
18 | public void addMinTypeExprent(Exprent exprent, VarType type) {
19 | minTypeExprents.add(new ExprentTypePair(exprent, type));
20 | }
21 |
22 | public List getMaxTypeExprents() {
23 | return maxTypeExprents;
24 | }
25 |
26 | public List getMinTypeExprents() {
27 | return minTypeExprents;
28 | }
29 |
30 | static class ExprentTypePair {
31 | public final Exprent exprent;
32 | public final VarType type;
33 |
34 | ExprentTypePair(Exprent exprent, VarType type) {
35 | this.exprent = exprent;
36 | this.type = type;
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/attr/StructAnnotationParameterAttribute.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.attr;
3 |
4 | import org.jetbrains.java.decompiler.modules.decompiler.exps.AnnotationExprent;
5 | import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
6 | import org.jetbrains.java.decompiler.util.DataInputFullStream;
7 |
8 | import java.io.IOException;
9 | import java.util.ArrayList;
10 | import java.util.Collections;
11 | import java.util.List;
12 |
13 | public class StructAnnotationParameterAttribute extends StructGeneralAttribute {
14 |
15 | private List> paramAnnotations;
16 |
17 | @Override
18 | public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException {
19 | int len = data.readUnsignedByte();
20 | if (len > 0) {
21 | paramAnnotations = new ArrayList<>(len);
22 | for (int i = 0; i < len; i++) {
23 | List annotations = StructAnnotationAttribute.parseAnnotations(pool, data);
24 | paramAnnotations.add(annotations);
25 | }
26 | }
27 | else {
28 | paramAnnotations = Collections.emptyList();
29 | }
30 | }
31 |
32 | public List> getParamAnnotations() {
33 | return paramAnnotations;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/attr/StructEnclosingMethodAttribute.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.attr;
3 |
4 | import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
5 | import org.jetbrains.java.decompiler.struct.consts.LinkConstant;
6 | import org.jetbrains.java.decompiler.util.DataInputFullStream;
7 |
8 | import java.io.IOException;
9 |
10 | public class StructEnclosingMethodAttribute extends StructGeneralAttribute {
11 |
12 | private String className;
13 | private String methodName;
14 | private String methodDescriptor;
15 |
16 | @Override
17 | public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException {
18 | int classIndex = data.readUnsignedShort();
19 | int methodIndex = data.readUnsignedShort();
20 |
21 | className = pool.getPrimitiveConstant(classIndex).getString();
22 | if (methodIndex != 0) {
23 | LinkConstant lk = pool.getLinkConstant(methodIndex);
24 | methodName = lk.elementname;
25 | methodDescriptor = lk.descriptor;
26 | }
27 | }
28 |
29 | public String getClassName() {
30 | return className;
31 | }
32 |
33 | public String getMethodDescriptor() {
34 | return methodDescriptor;
35 | }
36 |
37 | public String getMethodName() {
38 | return methodName;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/attr/StructRecordAttribute.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.attr;
3 |
4 | import org.jetbrains.java.decompiler.struct.StructRecordComponent;
5 | import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
6 | import org.jetbrains.java.decompiler.util.DataInputFullStream;
7 |
8 | import java.io.IOException;
9 | import java.util.Arrays;
10 | import java.util.Collections;
11 | import java.util.List;
12 |
13 | /*
14 | Record_attribute {
15 | u2 attribute_name_index;
16 | u4 attribute_length;
17 | u2 components_count;
18 | record_component_info components[components_count];
19 | }
20 | */
21 | public class StructRecordAttribute extends StructGeneralAttribute {
22 | List components;
23 |
24 | @Override
25 | public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException {
26 | int componentCount = data.readUnsignedShort();
27 | StructRecordComponent[] components = new StructRecordComponent[componentCount];
28 | for (int i = 0; i < componentCount; i++) {
29 | components[i] = StructRecordComponent.create(data, pool);
30 | }
31 | this.components = Arrays.asList(components);
32 | }
33 |
34 | public List getComponents() {
35 | return Collections.unmodifiableList(components);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/main/extern/IFernflowerLogger.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.main.extern;
3 |
4 | public abstract class IFernflowerLogger {
5 |
6 | public enum Severity {
7 | TRACE("TRACE: "), INFO("INFO: "), WARN("WARN: "), ERROR("ERROR: ");
8 |
9 | public final String prefix;
10 |
11 | Severity(String prefix) {
12 | this.prefix = prefix;
13 | }
14 | }
15 |
16 | private Severity severity = Severity.INFO;
17 |
18 | public boolean accepts(Severity severity) {
19 | return severity.ordinal() >= this.severity.ordinal();
20 | }
21 |
22 | public void setSeverity(Severity severity) {
23 | this.severity = severity;
24 | }
25 |
26 | public abstract void writeMessage(String message, Severity severity);
27 |
28 | public abstract void writeMessage(String message, Severity severity, Throwable t);
29 |
30 | public void writeMessage(String message, Throwable t) {
31 | writeMessage(message, Severity.ERROR, t);
32 | }
33 |
34 | public void startReadingClass(String className) { }
35 |
36 | public void endReadingClass() { }
37 |
38 | public void startClass(String className) { }
39 |
40 | public void endClass() { }
41 |
42 | public void startMethod(String methodName) { }
43 |
44 | public void endMethod() { }
45 |
46 | public void startWriteClass(String className) { }
47 |
48 | public void endWriteClass() { }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/attr/StructCodeAttribute.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.attr;
3 |
4 | import org.jetbrains.java.decompiler.struct.StructMember;
5 | import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
6 | import org.jetbrains.java.decompiler.util.DataInputFullStream;
7 |
8 | import java.io.IOException;
9 | import java.util.Map;
10 |
11 | /*
12 | u2 max_stack;
13 | u2 max_locals;
14 | u4 code_length;
15 | u1 code[];
16 | u2 exception_table_length;
17 | exception_table[] {
18 | u2 start_pc;
19 | u2 end_pc;
20 | u2 handler_pc;
21 | u2 catch_type;
22 | };
23 | u2 attributes_count;
24 | attribute_info attributes[];
25 | */
26 | public class StructCodeAttribute extends StructGeneralAttribute {
27 | public int localVariables = 0;
28 | public int codeLength = 0;
29 | public int codeFullLength = 0;
30 | public Map codeAttributes;
31 |
32 | @Override
33 | public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException {
34 | data.discard(2);
35 | localVariables = data.readUnsignedShort();
36 | codeLength = data.readInt();
37 | data.discard(codeLength);
38 | int excLength = data.readUnsignedShort();
39 | data.discard(excLength * 8);
40 | codeFullLength = codeLength + excLength * 8 + 2;
41 | codeAttributes = StructMember.readAttributes(data, pool);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/StructRecordComponent.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct;
3 |
4 | import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute;
5 | import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
6 | import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant;
7 | import org.jetbrains.java.decompiler.util.DataInputFullStream;
8 |
9 | import java.io.IOException;
10 | import java.util.Map;
11 |
12 | /*
13 | record_component_info {
14 | u2 name_index;
15 | u2 descriptor_index;
16 | u2 attributes_count;
17 | attribute_info attributes[attributes_count];
18 | }
19 | */
20 | public class StructRecordComponent extends StructField {
21 | public static StructRecordComponent create(DataInputFullStream in, ConstantPool pool) throws IOException {
22 | int nameIndex = in.readUnsignedShort();
23 | int descriptorIndex = in.readUnsignedShort();
24 |
25 | String name = ((PrimitiveConstant)pool.getConstant(nameIndex)).getString();
26 | String descriptor = ((PrimitiveConstant)pool.getConstant(descriptorIndex)).getString();
27 |
28 | Map attributes = readAttributes(in, pool);
29 |
30 | return new StructRecordComponent(0, attributes, name, descriptor);
31 | }
32 |
33 | private StructRecordComponent(int flags, Map attributes, String name, String descriptor) {
34 | super(flags, attributes, name, descriptor);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/consts/PrimitiveConstant.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.consts;
3 |
4 | public class PrimitiveConstant extends PooledConstant {
5 | public int index;
6 | public Object value;
7 | public boolean isArray;
8 |
9 | public PrimitiveConstant(int type, Object value) {
10 | super(type);
11 | this.value = value;
12 |
13 | initConstant();
14 | }
15 |
16 | public PrimitiveConstant(int type, int index) {
17 | super(type);
18 | this.index = index;
19 | }
20 |
21 | private void initConstant() {
22 | if (type == CONSTANT_Class) {
23 | String className = getString();
24 | isArray = (className.length() > 0 && className.charAt(0) == '['); // empty string for a class name seems to be possible in some android files
25 | }
26 | }
27 |
28 | public String getString() {
29 | return (String)value;
30 | }
31 |
32 | @Override
33 | public void resolveConstant(ConstantPool pool) {
34 | if (type == CONSTANT_Class || type == CONSTANT_String || type == CONSTANT_MethodType || type == CONSTANT_Module || type == CONSTANT_Package) {
35 | value = pool.getPrimitiveConstant(index).getString();
36 | initConstant();
37 | }
38 | }
39 |
40 | @Override
41 | public boolean equals(Object o) {
42 | if (o == this) return true;
43 | if (!(o instanceof PrimitiveConstant cn)) return false;
44 |
45 | return this.type == cn.type &&
46 | this.isArray == cn.isArray &&
47 | this.value.equals(cn.value);
48 | }
49 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/util/ListStack.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.util;
3 |
4 | import java.util.ArrayList;
5 |
6 | public class ListStack extends ArrayList {
7 | private int pointer = 0;
8 |
9 | public ListStack() {
10 | super();
11 | }
12 |
13 | public ListStack(int initialCapacity) {
14 | super(initialCapacity);
15 | }
16 |
17 | private ListStack(ArrayList extends T> list) {
18 | super(list);
19 | }
20 |
21 | public ListStack copy() {
22 | ListStack copy = new ListStack<>(this);
23 | copy.pointer = this.pointer;
24 | return copy;
25 | }
26 |
27 | public void push(T item) {
28 | this.add(item);
29 | pointer++;
30 | }
31 |
32 | public T pop() {
33 | pointer--;
34 | T o = this.get(pointer);
35 | this.remove(pointer);
36 | return o;
37 | }
38 |
39 | public T pop(int count) {
40 | T o = null;
41 | for (int i = count; i > 0; i--) {
42 | o = this.pop();
43 | }
44 | return o;
45 | }
46 |
47 | public void removeMultiple(int count) {
48 | while (count > 0) {
49 | pointer--;
50 | this.remove(pointer);
51 | count--;
52 | }
53 | }
54 |
55 | public T getByOffset(int offset) {
56 | return this.get(pointer + offset);
57 | }
58 |
59 | public void insertByOffset(int offset, T item) {
60 | this.add(pointer + offset, item);
61 | pointer++;
62 | }
63 |
64 | @Override
65 | public void clear() {
66 | super.clear();
67 | pointer = 0;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/attr/StructLineNumberTableAttribute.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.attr;
3 |
4 | import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
5 | import org.jetbrains.java.decompiler.util.DataInputFullStream;
6 | import org.jetbrains.java.decompiler.util.InterpreterUtil;
7 |
8 | import java.io.IOException;
9 |
10 | /**
11 | * u2 line_number_table_length;
12 | * { u2 start_pc;
13 | * u2 line_number;
14 | * } line_number_table[line_number_table_length];
15 | *
16 | * Created by Egor on 05.10.2014.
17 | */
18 | public class StructLineNumberTableAttribute extends StructGeneralAttribute {
19 | private int[] myLineInfo = InterpreterUtil.EMPTY_INT_ARRAY;
20 |
21 | @Override
22 | public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException {
23 | int len = data.readUnsignedShort() * 2;
24 | if (len > 0) {
25 | myLineInfo = new int[len];
26 | for (int i = 0; i < len; i += 2) {
27 | myLineInfo[i] = data.readUnsignedShort();
28 | myLineInfo[i + 1] = data.readUnsignedShort();
29 | }
30 | }
31 | else if (myLineInfo.length > 0) {
32 | myLineInfo = InterpreterUtil.EMPTY_INT_ARRAY;
33 | }
34 | }
35 |
36 | public int findLineNumber(int pc) {
37 | if (myLineInfo.length >= 2) {
38 | for (int i = myLineInfo.length - 2; i >= 0; i -= 2) {
39 | if (pc >= myLineInfo[i]) {
40 | return myLineInfo[i + 1];
41 | }
42 | }
43 | }
44 | return -1;
45 | }
46 |
47 | public int[] getRawData() {
48 | return myLineInfo;
49 | }
50 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/sforms/DirectNode.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler.sforms;
3 |
4 | import org.jetbrains.annotations.NotNull;
5 | import org.jetbrains.annotations.Nullable;
6 | import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
7 | import org.jetbrains.java.decompiler.modules.decompiler.stats.BasicBlockStatement;
8 | import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
9 |
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 |
14 | public class DirectNode {
15 | public final @NotNull DirectNodeType type;
16 | public final @NotNull String id;
17 | public final @NotNull Statement statement;
18 | public final @Nullable BasicBlockStatement block;
19 | public final List successors = new ArrayList<>();
20 | public final List predecessors = new ArrayList<>();
21 | public List exprents = new ArrayList<>();
22 |
23 | public DirectNode(@NotNull DirectNodeType type, @NotNull Statement statement, @NotNull String id) {
24 | this.type = type;
25 | this.statement = statement;
26 | this.id = id;
27 | this.block = null;
28 | }
29 |
30 | public DirectNode(@NotNull DirectNodeType type, @NotNull Statement statement, @NotNull BasicBlockStatement block) {
31 | this.type = type;
32 | this.statement = statement;
33 | this.id = Integer.toString(block.id);
34 | this.block = block;
35 | }
36 |
37 | @Override
38 | public String toString() {
39 | return id;
40 | }
41 |
42 | public enum DirectNodeType {
43 | DIRECT,
44 | TAIL,
45 | INIT,
46 | CONDITION,
47 | INCREMENT,
48 | TRY
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/Statements.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler.stats;
3 |
4 | import org.jetbrains.java.decompiler.main.rels.ClassWrapper;
5 | import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
6 | import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
7 | import org.jetbrains.java.decompiler.modules.decompiler.exps.InvocationExprent;
8 | import org.jetbrains.java.decompiler.modules.decompiler.exps.VarExprent;
9 | import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
10 |
11 | public final class Statements {
12 | public static Statement findFirstData(Statement stat) {
13 | if (stat.getExprents() != null) {
14 | return stat;
15 | }
16 | else if (stat.isLabeled()) { // FIXME: Why??
17 | return null;
18 | }
19 |
20 | return switch (stat.type) {
21 | case SEQUENCE, IF, ROOT, SWITCH, SYNCHRONIZED -> findFirstData(stat.getFirst());
22 | default -> null;
23 | };
24 | }
25 |
26 | public static boolean isInvocationInitConstructor(InvocationExprent inv, MethodWrapper method, ClassWrapper wrapper, boolean withThis) {
27 | if (inv.getFuncType() == InvocationExprent.TYPE_INIT && inv.getInstance().type == Exprent.EXPRENT_VAR) {
28 | VarExprent instVar = (VarExprent)inv.getInstance();
29 | VarVersionPair varPair = new VarVersionPair(instVar);
30 | String className = method.varproc.getThisVars().get(varPair);
31 | if (className != null) { // any this instance. TODO: Restrict to current class?
32 | return withThis || !wrapper.getClassStruct().qualifiedName.equals(inv.getClassName());
33 | }
34 | }
35 |
36 | return false;
37 | }
38 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/main/rels/MethodWrapper.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.main.rels;
3 |
4 | import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
5 | import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectGraph;
6 | import org.jetbrains.java.decompiler.modules.decompiler.sforms.FlattenStatementsHelper;
7 | import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
8 | import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
9 | import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
10 | import org.jetbrains.java.decompiler.struct.StructMethod;
11 |
12 | import java.util.HashSet;
13 | import java.util.List;
14 | import java.util.Set;
15 |
16 | public class MethodWrapper {
17 | public final RootStatement root;
18 | public final VarProcessor varproc;
19 | public final StructMethod methodStruct;
20 | public final CounterContainer counter;
21 | public final Set setOuterVarNames = new HashSet<>();
22 |
23 | public DirectGraph graph;
24 | public List synthParameters;
25 | public boolean decompiledWithErrors;
26 |
27 | public MethodWrapper(RootStatement root, VarProcessor varproc, StructMethod methodStruct, CounterContainer counter) {
28 | this.root = root;
29 | this.varproc = varproc;
30 | this.methodStruct = methodStruct;
31 | this.counter = counter;
32 | }
33 |
34 | public DirectGraph getOrBuildGraph() {
35 | if (graph == null && root != null) {
36 | graph = new FlattenStatementsHelper().buildDirectGraph(root);
37 | }
38 | return graph;
39 | }
40 |
41 | @Override
42 | public String toString() {
43 | return methodStruct.getName();
44 | }
45 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/attr/StructMethodParametersAttribute.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
3 | */
4 | package org.jetbrains.java.decompiler.struct.attr;
5 |
6 | import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
7 | import org.jetbrains.java.decompiler.util.DataInputFullStream;
8 |
9 | import java.io.IOException;
10 | import java.util.ArrayList;
11 | import java.util.Collections;
12 | import java.util.List;
13 |
14 | /*
15 | u1 parameters_count;
16 | { u2 name_index;
17 | u2 access_flags;
18 | } parameters[parameters_count];
19 | */
20 | public class StructMethodParametersAttribute extends StructGeneralAttribute {
21 | private List myEntries;
22 |
23 | @Override
24 | public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException {
25 | int len = data.readUnsignedByte();
26 | List entries;
27 | if (len > 0) {
28 | entries = new ArrayList<>(len);
29 |
30 | for (int i = 0; i < len; i++) {
31 | int nameIndex = data.readUnsignedShort();
32 | String name = nameIndex != 0 ? pool.getPrimitiveConstant(nameIndex).getString() : null;
33 | int access_flags = data.readUnsignedShort();
34 | entries.add(new Entry(name, access_flags));
35 | }
36 | }
37 | else {
38 | entries = Collections.emptyList();
39 | }
40 | myEntries = Collections.unmodifiableList(entries);
41 | }
42 |
43 | public List getEntries() {
44 | return myEntries;
45 | }
46 |
47 | public static class Entry {
48 | public final String myName;
49 | public final int myAccessFlags;
50 |
51 | public Entry(String name, int accessFlags) {
52 | myName = name;
53 | myAccessFlags = accessFlags;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionNode.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler.vars;
3 |
4 | import org.jetbrains.java.decompiler.modules.decompiler.decompose.IGraphNode;
5 | import org.jetbrains.java.decompiler.util.SFormsFastMapDirect;
6 |
7 | import java.util.ArrayList;
8 | import java.util.HashSet;
9 | import java.util.List;
10 | import java.util.Set;
11 |
12 | public class VarVersionNode implements IGraphNode {
13 | public static final int FLAG_PHANTOM_FIN_EXIT = 2;
14 |
15 | public final int var;
16 | public final int version;
17 | public final Set predecessors = new HashSet<>();
18 | public final Set successors = new HashSet<>();
19 |
20 | public int flags;
21 | public SFormsFastMapDirect live = new SFormsFastMapDirect();
22 |
23 | public VarVersionNode(int var, int version) {
24 | this.var = var;
25 | this.version = version;
26 | }
27 |
28 | public void addPredecessor(VarVersionEdge edge) {
29 | predecessors.add(edge);
30 | }
31 |
32 | public void removePredecessor(VarVersionEdge edge) {
33 | predecessors.remove(edge);
34 | }
35 |
36 | public void addSuccessor(VarVersionEdge edge) {
37 | successors.add(edge);
38 | }
39 |
40 | public void removeSuccessor(VarVersionEdge edge) {
41 | successors.remove(edge);
42 | }
43 |
44 | @Override
45 | public List getPredecessorNodes() {
46 | List lst = new ArrayList<>(predecessors.size());
47 | for (VarVersionEdge edge : predecessors) {
48 | lst.add(edge.source);
49 | }
50 | return lst;
51 | }
52 |
53 | @Override
54 | public String toString() {
55 | return "(" + var + '_' + version + ')';
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/gen/FieldDescriptor.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
2 | package org.jetbrains.java.decompiler.struct.gen;
3 |
4 | import org.jetbrains.java.decompiler.code.CodeConstants;
5 |
6 | public final class FieldDescriptor {
7 | public static final FieldDescriptor SHORT_DESCRIPTOR = parseDescriptor("Ljava/lang/Short;");
8 | public static final FieldDescriptor INTEGER_DESCRIPTOR = parseDescriptor("Ljava/lang/Integer;");
9 | public static final FieldDescriptor LONG_DESCRIPTOR = parseDescriptor("Ljava/lang/Long;");
10 | public static final FieldDescriptor FLOAT_DESCRIPTOR = parseDescriptor("Ljava/lang/Float;");
11 | public static final FieldDescriptor DOUBLE_DESCRIPTOR = parseDescriptor("Ljava/lang/Double;");
12 |
13 | public final VarType type;
14 | public final String descriptorString;
15 |
16 | private FieldDescriptor(String descriptor) {
17 | type = new VarType(descriptor);
18 | descriptorString = descriptor;
19 | }
20 |
21 | public static FieldDescriptor parseDescriptor(String descriptor) {
22 | return new FieldDescriptor(descriptor);
23 | }
24 |
25 | public String buildNewDescriptor(NewClassNameBuilder builder) {
26 | if (type.getType() == CodeConstants.TYPE_OBJECT) {
27 | String newClassName = builder.buildNewClassname(type.getValue());
28 | if (newClassName != null) {
29 | return new VarType(type.getType(), type.getArrayDim(), newClassName).toString();
30 | }
31 | }
32 |
33 | return null;
34 | }
35 |
36 | @Override
37 | public boolean equals(Object o) {
38 | if (o == this) return true;
39 | if (!(o instanceof FieldDescriptor fd)) return false;
40 |
41 | return type.equals(fd.type);
42 | }
43 |
44 | @Override
45 | public int hashCode() {
46 | return type.hashCode();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/code/SwitchInstruction.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.code;
3 |
4 | public class SwitchInstruction extends Instruction {
5 | private int[] destinations;
6 | private int[] values;
7 | private int defaultDestination;
8 |
9 | public SwitchInstruction(int opcode, int group, boolean wide, int bytecodeVersion, int[] operands) {
10 | super(opcode, group, wide, bytecodeVersion, operands);
11 | }
12 |
13 | @Override
14 | public void initInstruction(InstructionSequence seq) {
15 | defaultDestination = seq.getPointerByRelOffset(operands[0]);
16 |
17 | int prefix = opcode == CodeConstants.opc_tableswitch ? 3 : 2;
18 | int len = operands.length - prefix;
19 | int low = 0;
20 | if (opcode == CodeConstants.opc_lookupswitch) {
21 | len /= 2;
22 | }
23 | else {
24 | low = operands[1];
25 | }
26 |
27 | destinations = new int[len];
28 | values = new int[len];
29 | for (int i = 0, k = 0; i < len; i++, k++) {
30 | if (opcode == CodeConstants.opc_lookupswitch) {
31 | values[i] = operands[prefix + k];
32 | k++;
33 | }
34 | else {
35 | values[i] = low + k;
36 | }
37 | destinations[i] = seq.getPointerByRelOffset(operands[prefix + k]);
38 | }
39 | }
40 |
41 | public int[] getDestinations() {
42 | return destinations;
43 | }
44 |
45 | public int[] getValues() {
46 | return values;
47 | }
48 |
49 | public int getDefaultDestination() {
50 | return defaultDestination;
51 | }
52 |
53 | @Override
54 | public SwitchInstruction clone() {
55 | SwitchInstruction copy = (SwitchInstruction)super.clone();
56 | copy.defaultDestination = defaultDestination;
57 | copy.destinations = destinations.clone();
58 | copy.values = values.clone();
59 | return copy;
60 | }
61 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/attr/StructBootstrapMethodsAttribute.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.attr;
3 |
4 | import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
5 | import org.jetbrains.java.decompiler.struct.consts.LinkConstant;
6 | import org.jetbrains.java.decompiler.struct.consts.PooledConstant;
7 | import org.jetbrains.java.decompiler.util.DataInputFullStream;
8 |
9 | import java.io.IOException;
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | public class StructBootstrapMethodsAttribute extends StructGeneralAttribute {
14 |
15 | private final List methodRefs = new ArrayList<>();
16 | private final List> methodArguments = new ArrayList<>();
17 |
18 | @Override
19 | public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException {
20 | int method_number = data.readUnsignedShort();
21 |
22 | for (int i = 0; i < method_number; ++i) {
23 | int bootstrap_method_ref = data.readUnsignedShort();
24 | int num_bootstrap_arguments = data.readUnsignedShort();
25 |
26 | List list_arguments = new ArrayList<>();
27 |
28 | for (int j = 0; j < num_bootstrap_arguments; ++j) {
29 | int bootstrap_argument_ref = data.readUnsignedShort();
30 |
31 | list_arguments.add(pool.getConstant(bootstrap_argument_ref));
32 | }
33 |
34 | methodRefs.add(pool.getLinkConstant(bootstrap_method_ref));
35 | methodArguments.add(list_arguments);
36 | }
37 | }
38 |
39 | public int getMethodsNumber() {
40 | return methodRefs.size();
41 | }
42 |
43 | public LinkConstant getMethodReference(int index) {
44 | return methodRefs.get(index);
45 | }
46 |
47 | public List getMethodArguments(int index) {
48 | return methodArguments.get(index);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/main/decompiler/shxjia/CustomeResultSaver.java:
--------------------------------------------------------------------------------
1 | package org.jetbrains.java.decompiler.main.decompiler.shxjia;
2 |
3 | import org.jetbrains.java.decompiler.main.DecompilerContext;
4 | import org.jetbrains.java.decompiler.main.extern.IResultSaver;
5 | import org.jetbrains.java.decompiler.util.InterpreterUtil;
6 |
7 | import java.io.File;
8 | import java.io.IOException;
9 | import java.nio.charset.StandardCharsets;
10 | import java.nio.file.Files;
11 | import java.nio.file.Paths;
12 | import java.util.jar.Manifest;
13 |
14 | public class CustomeResultSaver implements IResultSaver {
15 | @Override
16 | public void saveFolder(String path) {
17 |
18 | }
19 |
20 | @Override
21 | public void copyFile(String source, String path, String entryName) {
22 | try {
23 | InterpreterUtil.copyFile(new File(source), new File(path));
24 | } catch (IOException ex) {
25 | DecompilerContext.getLogger().writeMessage("Cannot copy " + source + " to " + entryName, ex);
26 | }
27 | }
28 |
29 | @Override
30 | public void saveClassFile(String path, String qualifiedName, String entryName, String content, int[] mapping) {
31 |
32 | try {
33 | Files.write(Paths.get(path), content.getBytes(StandardCharsets.UTF_8));
34 | } catch (Exception e) {
35 |
36 | }
37 | }
38 |
39 | @Override
40 | public void createArchive(String path, String archiveName, Manifest manifest) {
41 | }
42 |
43 | @Override
44 | public void saveDirEntry(String path, String archiveName, String entryName) {
45 | }
46 |
47 | @Override
48 | public void copyEntry(String source, String path, String archiveName, String entry) {
49 | }
50 |
51 | @Override
52 | public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content) {
53 | }
54 |
55 | @Override
56 | public void closeArchive(String path, String archiveName) {
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/match/MatchNode.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.match;
3 |
4 | import org.jetbrains.java.decompiler.struct.match.IMatchable.MatchProperties;
5 |
6 | import java.util.ArrayList;
7 | import java.util.HashMap;
8 | import java.util.List;
9 | import java.util.Map;
10 |
11 | public class MatchNode {
12 | public static class RuleValue {
13 | public final int parameter;
14 | public final Object value;
15 |
16 | public RuleValue(int parameter, Object value) {
17 | this.parameter = parameter;
18 | this.value = value;
19 | }
20 |
21 | public boolean isVariable() {
22 | String strValue = value.toString();
23 | return (strValue.charAt(0) == '$' && strValue.charAt(strValue.length() - 1) == '$');
24 | }
25 |
26 | public String toString() {
27 | return value.toString();
28 | }
29 | }
30 |
31 | public static final int MATCHNODE_STATEMENT = 0;
32 | public static final int MATCHNODE_EXPRENT = 1;
33 |
34 | private final int type;
35 | private final Map rules = new HashMap<>();
36 | private final List children = new ArrayList<>();
37 |
38 | public MatchNode(int type) {
39 | this.type = type;
40 | }
41 |
42 | public void addChild(MatchNode child) {
43 | children.add(child);
44 | }
45 |
46 | public void addRule(MatchProperties property, RuleValue value) {
47 | rules.put(property, value);
48 | }
49 |
50 | public int getType() {
51 | return type;
52 | }
53 |
54 | public List getChildren() {
55 | return children;
56 | }
57 |
58 | public Map getRules() {
59 | return rules;
60 | }
61 |
62 | public Object getRuleValue(MatchProperties property) {
63 | RuleValue rule = rules.get(property);
64 | return rule == null ? null : rule.value;
65 | }
66 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/GeneralStatement.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler.stats;
3 |
4 | import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
5 | import org.jetbrains.java.decompiler.util.TextBuffer;
6 |
7 | import java.util.Collection;
8 | import java.util.HashSet;
9 |
10 |
11 | public class GeneralStatement extends Statement {
12 |
13 | // *****************************************************************************
14 | // constructors
15 | // *****************************************************************************
16 |
17 | private GeneralStatement() {
18 | super(StatementType.GENERAL);
19 | }
20 |
21 | public GeneralStatement(Statement head, Collection extends Statement> statements, Statement post) {
22 |
23 | this();
24 |
25 | first = head;
26 | stats.addWithKey(head, head.id);
27 |
28 | HashSet set = new HashSet<>(statements);
29 | set.remove(head);
30 |
31 | for (Statement st : set) {
32 | stats.addWithKey(st, st.id);
33 | }
34 |
35 | this.post = post;
36 | }
37 |
38 | // *****************************************************************************
39 | // public methods
40 | // *****************************************************************************
41 |
42 | @Override
43 | public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
44 | TextBuffer buf = new TextBuffer();
45 |
46 | if (isLabeled()) {
47 | buf.appendIndent(indent).append("label").append(Integer.toString(id)).append(":").appendLineSeparator();
48 | }
49 |
50 | buf.appendIndent(indent).append("abstract statement {").appendLineSeparator();
51 | for (Statement stat : stats) {
52 | buf.append(stat.toJava(indent + 1, tracer));
53 | }
54 | buf.appendIndent(indent).append("}");
55 |
56 | return buf;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/StructTypePathEntry.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
2 | package org.jetbrains.java.decompiler.struct;
3 |
4 | /**
5 | * An entry in the type path which indicates the path of a type annotation.
6 | */
7 | public class StructTypePathEntry {
8 | private final int typePathEntryKind;
9 | private final int typeArgumentIndex;
10 |
11 | public StructTypePathEntry(int typePathKind, int typeArgumentIndex) {
12 | this.typePathEntryKind = typePathKind;
13 | this.typeArgumentIndex = typeArgumentIndex;
14 | }
15 |
16 | /**
17 | * @return The type argument index, indicating which nested type argument is annotated. The index starts at 0.
18 | */
19 | public int getTypeArgumentIndex() {
20 | return typeArgumentIndex;
21 | }
22 |
23 | /**
24 | * @return {@link Kind#id} of this type path entry.
25 | */
26 | public int getTypePathEntryKind() {
27 | return typePathEntryKind;
28 | }
29 |
30 | /**
31 | * The type_path_kind.
32 | *
33 | * @see The JVM class File Format Spec Table 4.7.20.2 A
34 | */
35 | public enum Kind {
36 | /**
37 | * Type path entry is an array type contained in e.g. @I String[] @G [] @H []
38 | */
39 | ARRAY(0),
40 |
41 | /**
42 | * Type path entry is a nested type contained in e.g. Outer . @B Middle . @C Inner
43 | */
44 | NESTED(1),
45 |
46 | /**
47 | * Type path entry is a wildcard contained in e.g. Map<@B ? extends String, String>
48 | */
49 | TYPE_WILDCARD(2),
50 |
51 | /**
52 | * Type path entry is a type argument of a parameterized type contained in e.g. List<@B Comparable<@F Object>>
53 | */
54 | TYPE(3);
55 |
56 | private final int id;
57 |
58 | Kind(int id) {
59 | this.id = id;
60 | }
61 |
62 | public int getId() {
63 | return id;
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/StructField.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
2 | package org.jetbrains.java.decompiler.struct;
3 |
4 | import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute;
5 | import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
6 | import org.jetbrains.java.decompiler.struct.gen.Type;
7 | import org.jetbrains.java.decompiler.struct.gen.VarType;
8 | import org.jetbrains.java.decompiler.util.DataInputFullStream;
9 |
10 | import java.io.IOException;
11 | import java.util.Map;
12 |
13 | /*
14 | field_info {
15 | u2 access_flags;
16 | u2 name_index;
17 | u2 descriptor_index;
18 | u2 attributes_count;
19 | attribute_info attributes[attributes_count];
20 | }
21 | */
22 | public class StructField extends StructMember {
23 | public static StructField create(DataInputFullStream in, ConstantPool pool, String clQualifiedName) throws IOException {
24 | int accessFlags = in.readUnsignedShort();
25 | int nameIndex = in.readUnsignedShort();
26 | int descriptorIndex = in.readUnsignedShort();
27 |
28 | String[] values = pool.getClassElement(ConstantPool.FIELD, clQualifiedName, nameIndex, descriptorIndex);
29 |
30 | Map attributes = readAttributes(in, pool);
31 |
32 | return new StructField(accessFlags, attributes, values[0], values[1]);
33 | }
34 |
35 | private final String name;
36 | private final String descriptor;
37 |
38 | protected StructField(int accessFlags, Map attributes, String name, String descriptor) {
39 | super(accessFlags, attributes);
40 | this.name = name;
41 | this.descriptor = descriptor;
42 | }
43 |
44 | public final String getName() {
45 | return name;
46 | }
47 |
48 | public final String getDescriptor() {
49 | return descriptor;
50 | }
51 |
52 | @Override
53 | public String toString() {
54 | return name;
55 | }
56 |
57 | @Override
58 | protected Type getType() {
59 | return new VarType(descriptor);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/TypeAnnotation.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler.exps;
3 |
4 | public class TypeAnnotation {
5 | public static final int CLASS_TYPE_PARAMETER = 0x00;
6 | public static final int METHOD_TYPE_PARAMETER = 0x01;
7 | public static final int SUPER_TYPE_REFERENCE = 0x10;
8 | public static final int CLASS_TYPE_PARAMETER_BOUND = 0x11;
9 | public static final int METHOD_TYPE_PARAMETER_BOUND = 0x12;
10 | public static final int FIELD = 0x13;
11 | public static final int METHOD_RETURN_TYPE = 0x14;
12 | public static final int METHOD_RECEIVER = 0x15;
13 | public static final int METHOD_PARAMETER = 0x16;
14 | public static final int THROWS_REFERENCE = 0x17;
15 | public static final int LOCAL_VARIABLE = 0x40;
16 | public static final int RESOURCE_VARIABLE = 0x41;
17 | public static final int CATCH_CLAUSE = 0x42;
18 | public static final int EXPR_INSTANCEOF = 0x43;
19 | public static final int EXPR_NEW = 0x44;
20 | public static final int EXPR_CONSTRUCTOR_REF = 0x45;
21 | public static final int EXPR_METHOD_REF = 0x46;
22 | public static final int TYPE_ARG_CAST = 0x47;
23 | public static final int TYPE_ARG_CONSTRUCTOR_CALL = 0x48;
24 | public static final int TYPE_ARG_METHOD_CALL = 0x49;
25 | public static final int TYPE_ARG_CONSTRUCTOR_REF = 0x4A;
26 | public static final int TYPE_ARG_METHOD_REF = 0x4B;
27 |
28 | private final int target;
29 | private final byte[] path;
30 | private final AnnotationExprent annotation;
31 |
32 | public TypeAnnotation(int target, byte[] path, AnnotationExprent annotation) {
33 | this.target = target;
34 | this.path = path;
35 | this.annotation = annotation;
36 | }
37 |
38 | public int getTargetType() {
39 | return target >> 24;
40 | }
41 |
42 | public int getIndex() {
43 | return target & 0x0FFFF;
44 | }
45 |
46 | public boolean isTopLevel() {
47 | return path == null;
48 | }
49 |
50 | public AnnotationExprent getAnnotation() {
51 | return annotation;
52 | }
53 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/typeann/TypeAnnotationWriteHelper.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
2 | package org.jetbrains.java.decompiler.modules.decompiler.typeann;
3 |
4 | import org.jetbrains.annotations.NotNull;
5 | import org.jetbrains.java.decompiler.struct.StructTypePathEntry;
6 | import org.jetbrains.java.decompiler.util.TextBuffer;
7 |
8 | import java.util.ArrayDeque;
9 | import java.util.Deque;
10 | import java.util.List;
11 | import java.util.stream.Collectors;
12 |
13 | /**
14 | * Wrapper around {@link TypeAnnotation} to maintain the state of the {@link StructTypePathEntry} list while writing.
15 | */
16 | public class TypeAnnotationWriteHelper {
17 | private final @NotNull Deque paths;
18 |
19 | private final @NotNull TypeAnnotation annotation;
20 |
21 | public TypeAnnotationWriteHelper(@NotNull TypeAnnotation annotation) {
22 | this(annotation, new ArrayDeque<>(annotation.getPaths()));
23 | }
24 |
25 | public TypeAnnotationWriteHelper(@NotNull TypeAnnotation annotation, @NotNull Deque paths) {
26 | this.annotation = annotation;
27 | this.paths = paths;
28 | }
29 |
30 | /**
31 | * @return Active path relative to the current scope when writing.
32 | */
33 | public @NotNull Deque getPaths() {
34 | return paths;
35 | }
36 |
37 | /**
38 | * @return The annotation to write
39 | */
40 | public @NotNull TypeAnnotation getAnnotation() {
41 | return annotation;
42 | }
43 |
44 | public void writeTo(@NotNull StringBuilder sb) {
45 | annotation.writeTo(sb);
46 | }
47 |
48 | public void writeTo(@NotNull TextBuffer sb) {
49 | annotation.writeTo(sb);
50 | }
51 |
52 | public int arrayPathCount() {
53 | return (int) paths.stream().filter(entry -> entry.getTypePathEntryKind() == StructTypePathEntry.Kind.ARRAY.getId()).count();
54 | }
55 |
56 | public static List create(List typeAnnotations) {
57 | return typeAnnotations.stream()
58 | .map(TypeAnnotationWriteHelper::new)
59 | .collect(Collectors.toList());
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/MonitorExprent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
3 | */
4 | package org.jetbrains.java.decompiler.modules.decompiler.exps;
5 |
6 | import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
7 | import org.jetbrains.java.decompiler.util.TextBuffer;
8 |
9 | import java.util.ArrayList;
10 | import java.util.List;
11 | import java.util.Objects;
12 | import java.util.Set;
13 |
14 | public class MonitorExprent extends Exprent {
15 |
16 | public static final int MONITOR_ENTER = 0;
17 | public static final int MONITOR_EXIT = 1;
18 |
19 | private final int monType;
20 | private Exprent value;
21 |
22 | public MonitorExprent(int monType, Exprent value, Set bytecodeOffsets) {
23 | super(EXPRENT_MONITOR);
24 | this.monType = monType;
25 | this.value = value;
26 |
27 | addBytecodeOffsets(bytecodeOffsets);
28 | }
29 |
30 | @Override
31 | public Exprent copy() {
32 | return new MonitorExprent(monType, value.copy(), bytecode);
33 | }
34 |
35 | @Override
36 | public List getAllExprents() {
37 | List lst = new ArrayList<>();
38 | lst.add(value);
39 | return lst;
40 | }
41 |
42 | @Override
43 | public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
44 | tracer.addMapping(bytecode);
45 |
46 | if (monType == MONITOR_ENTER) {
47 | return value.toJava(indent, tracer).enclose("synchronized(", ")");
48 | }
49 | else {
50 | return new TextBuffer();
51 | }
52 | }
53 |
54 | @Override
55 | public void replaceExprent(Exprent oldExpr, Exprent newExpr) {
56 | if (oldExpr == value) {
57 | value = newExpr;
58 | }
59 | }
60 |
61 | @Override
62 | public boolean equals(Object o) {
63 | if (o == this) return true;
64 | if (!(o instanceof MonitorExprent me)) return false;
65 |
66 | return monType == me.getMonType() &&
67 | Objects.equals(value, me.getValue());
68 | }
69 |
70 | public int getMonType() {
71 | return monType;
72 | }
73 |
74 | public Exprent getValue() {
75 | return value;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/ExprUtil.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler.exps;
3 |
4 | import org.jetbrains.java.decompiler.code.CodeConstants;
5 | import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
6 | import org.jetbrains.java.decompiler.main.DecompilerContext;
7 | import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
8 | import org.jetbrains.java.decompiler.main.rels.ClassWrapper;
9 | import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
10 | import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
11 |
12 | import java.util.ArrayList;
13 | import java.util.Collections;
14 | import java.util.List;
15 |
16 | public final class ExprUtil {
17 | public static List getSyntheticParametersMask(String className, String descriptor, int parameters) {
18 | ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(className);
19 | return node != null ? getSyntheticParametersMask(node, descriptor, parameters) : null;
20 | }
21 |
22 | public static List getSyntheticParametersMask(ClassNode node, String descriptor, int parameters) {
23 | List mask = null;
24 |
25 | ClassWrapper wrapper = node.getWrapper();
26 | if (wrapper != null) {
27 | // own class
28 | MethodWrapper methodWrapper = wrapper.getMethodWrapper(CodeConstants.INIT_NAME, descriptor);
29 | if (methodWrapper == null) {
30 | if (DecompilerContext.getOption(IFernflowerPreferences.IGNORE_INVALID_BYTECODE)) {
31 | return null;
32 | }
33 | throw new RuntimeException("Constructor " + node.classStruct.qualifiedName + "." + CodeConstants.INIT_NAME + descriptor + " not found");
34 | }
35 | mask = methodWrapper.synthParameters;
36 | }
37 | else if (parameters > 0 && node.type == ClassNode.CLASS_MEMBER && (node.access & CodeConstants.ACC_STATIC) == 0) {
38 | // non-static member class
39 | mask = new ArrayList<>(Collections.nCopies(parameters, null));
40 | mask.set(0, new VarVersionPair(-1, 0));
41 | }
42 |
43 | return mask;
44 | }
45 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/gen/DataPoint.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
2 | package org.jetbrains.java.decompiler.struct.gen;
3 |
4 | import org.jetbrains.java.decompiler.code.CodeConstants;
5 | import org.jetbrains.java.decompiler.struct.StructMethod;
6 | import org.jetbrains.java.decompiler.util.ListStack;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | public class DataPoint {
12 | private final List localVariables;
13 | private final ListStack stack;
14 |
15 | public DataPoint() {
16 | this(new ArrayList<>(), new ListStack<>());
17 | }
18 |
19 | private DataPoint(List localVariables, ListStack stack) {
20 | this.localVariables = localVariables;
21 | this.stack = stack;
22 | }
23 |
24 | public DataPoint copy() {
25 | return new DataPoint(new ArrayList<>(localVariables), stack.copy());
26 | }
27 |
28 | public void setVariable(int index, VarType value) {
29 | if (index >= localVariables.size()) {
30 | for (int i = localVariables.size(); i <= index; i++) {
31 | localVariables.add(new VarType(CodeConstants.TYPE_NOTINITIALIZED));
32 | }
33 | }
34 |
35 | localVariables.set(index, value);
36 | }
37 |
38 | public VarType getVariable(int index) {
39 | if (index < localVariables.size()) {
40 | return localVariables.get(index);
41 | }
42 | else {
43 | return new VarType(CodeConstants.TYPE_NOTINITIALIZED);
44 | }
45 | }
46 |
47 | public static DataPoint getInitialDataPoint(StructMethod mt) {
48 | DataPoint point = new DataPoint();
49 |
50 | MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
51 |
52 | int k = 0;
53 | if (!mt.hasModifier(CodeConstants.ACC_STATIC)) {
54 | point.setVariable(k++, new VarType(CodeConstants.TYPE_OBJECT, 0, null));
55 | }
56 |
57 | for (int i = 0; i < md.params.length; i++) {
58 | VarType var = md.params[i];
59 |
60 | point.setVariable(k++, var);
61 | if (var.getStackSize() == 2) {
62 | point.setVariable(k++, new VarType(CodeConstants.TYPE_GROUP2EMPTY));
63 | }
64 | }
65 |
66 | return point;
67 | }
68 |
69 | public ListStack getStack() {
70 | return stack;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/attr/StructInnerClassesAttribute.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.attr;
3 |
4 | import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
5 | import org.jetbrains.java.decompiler.util.DataInputFullStream;
6 |
7 | import java.io.IOException;
8 | import java.util.ArrayList;
9 | import java.util.Collections;
10 | import java.util.List;
11 |
12 | public class StructInnerClassesAttribute extends StructGeneralAttribute {
13 | public static final class Entry {
14 | public final int outerNameIdx;
15 | public final int simpleNameIdx;
16 | public final int accessFlags;
17 | public final String innerName;
18 | public final String enclosingName;
19 | public final String simpleName;
20 |
21 | private Entry(int outerNameIdx, int simpleNameIdx, int accessFlags, String innerName, String enclosingName, String simpleName) {
22 | this.outerNameIdx = outerNameIdx;
23 | this.simpleNameIdx = simpleNameIdx;
24 | this.accessFlags = accessFlags;
25 | this.innerName = innerName;
26 | this.enclosingName = enclosingName;
27 | this.simpleName = simpleName;
28 | }
29 | }
30 |
31 | private List entries;
32 |
33 | @Override
34 | public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException {
35 | int len = data.readUnsignedShort();
36 | if (len > 0) {
37 | entries = new ArrayList<>(len);
38 |
39 | for (int i = 0; i < len; i++) {
40 | int innerNameIdx = data.readUnsignedShort();
41 | int outerNameIdx = data.readUnsignedShort();
42 | int simpleNameIdx = data.readUnsignedShort();
43 | int accessFlags = data.readUnsignedShort();
44 |
45 | String innerName = pool.getPrimitiveConstant(innerNameIdx).getString();
46 | String outerName = outerNameIdx != 0 ? pool.getPrimitiveConstant(outerNameIdx).getString() : null;
47 | String simpleName = simpleNameIdx != 0 ? pool.getPrimitiveConstant(simpleNameIdx).getString() : null;
48 |
49 | entries.add(new Entry(outerNameIdx, simpleNameIdx, accessFlags, innerName, outerName, simpleName));
50 | }
51 | }
52 | else {
53 | entries = Collections.emptyList();
54 | }
55 | }
56 |
57 | public List getEntries() {
58 | return entries;
59 | }
60 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/ClasspathHelper.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
2 | package org.jetbrains.java.decompiler.modules.decompiler;
3 |
4 | import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
5 | import org.jetbrains.java.decompiler.struct.gen.VarType;
6 |
7 | import java.lang.reflect.Method;
8 | import java.util.Collections;
9 | import java.util.HashMap;
10 | import java.util.Map;
11 |
12 | public final class ClasspathHelper {
13 |
14 | private static final Map METHOD_CACHE = Collections.synchronizedMap(new HashMap<>());
15 |
16 | public static Method findMethod(String classname, String methodName, MethodDescriptor descriptor) {
17 | String targetClass = classname.replace('/', '.');
18 | String methodSignature = buildMethodSignature(targetClass + '.' + methodName, descriptor);
19 |
20 | Method method;
21 | if (METHOD_CACHE.containsKey(methodSignature)) {
22 | method = METHOD_CACHE.get(methodSignature);
23 | }
24 | else {
25 | method = findMethodOnClasspath(targetClass, methodSignature);
26 | METHOD_CACHE.put(methodSignature, method);
27 | }
28 |
29 | return method;
30 | }
31 |
32 | private static Method findMethodOnClasspath(String targetClass, String methodSignature) {
33 | try {
34 | // use bootstrap classloader to only provide access to JRE classes
35 | Class cls = new ClassLoader(null) {}.loadClass(targetClass);
36 | for (Method mtd : cls.getMethods()) {
37 | // use contains() to ignore access modifiers and thrown exceptions
38 | if (mtd.toString().contains(methodSignature)) {
39 | return mtd;
40 | }
41 | }
42 | }
43 | catch (Exception e) {
44 | // ignore
45 | }
46 | return null;
47 | }
48 |
49 | private static String buildMethodSignature(String name, MethodDescriptor md) {
50 | StringBuilder sb = new StringBuilder();
51 |
52 | appendType(sb, md.ret);
53 | sb.append(' ').append(name).append('(');
54 | for (VarType param : md.params) {
55 | appendType(sb, param);
56 | sb.append(',');
57 | }
58 | if (sb.charAt(sb.length() - 1) == ',') {
59 | sb.setLength(sb.length() - 1);
60 | }
61 | sb.append(')');
62 |
63 | return sb.toString();
64 | }
65 |
66 | private static void appendType(StringBuilder sb, VarType type) {
67 | sb.append(type.getValue().replace('/', '.'));
68 | for (int i = 0; i < type.getArrayDim(); i++) {
69 | sb.append("[]");
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/BasicBlockStatement.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.modules.decompiler.stats;
3 |
4 | import org.jetbrains.java.decompiler.code.CodeConstants;
5 | import org.jetbrains.java.decompiler.code.Instruction;
6 | import org.jetbrains.java.decompiler.code.SimpleInstructionSequence;
7 | import org.jetbrains.java.decompiler.code.cfg.BasicBlock;
8 | import org.jetbrains.java.decompiler.main.DecompilerContext;
9 | import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
10 | import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
11 | import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
12 | import org.jetbrains.java.decompiler.util.TextBuffer;
13 |
14 | public class BasicBlockStatement extends Statement {
15 | private final BasicBlock block;
16 |
17 | public BasicBlockStatement(BasicBlock block) {
18 | super(StatementType.BASIC_BLOCK, block.id);
19 | this.block = block;
20 |
21 | CounterContainer container = DecompilerContext.getCounterContainer();
22 | if (id >= container.getCounter(CounterContainer.STATEMENT_COUNTER)) {
23 | container.setCounter(CounterContainer.STATEMENT_COUNTER, id + 1);
24 | }
25 |
26 | Instruction instr = block.getLastInstruction();
27 | if (instr != null) {
28 | if (instr.group == CodeConstants.GROUP_JUMP && instr.opcode != CodeConstants.opc_goto) {
29 | lastBasicType = StatementType.IF;
30 | }
31 | else if (instr.group == CodeConstants.GROUP_SWITCH) {
32 | lastBasicType = StatementType.SWITCH;
33 | }
34 | }
35 |
36 | buildMonitorFlags();
37 | }
38 |
39 | @Override
40 | public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
41 | TextBuffer tb = ExprProcessor.listToJava(varDefinitions, indent, tracer);
42 | tb.append(ExprProcessor.listToJava(exprents, indent, tracer));
43 | return tb;
44 | }
45 |
46 | @Override
47 | public Statement getSimpleCopy() {
48 | int id = DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.STATEMENT_COUNTER);
49 |
50 | SimpleInstructionSequence seq = new SimpleInstructionSequence();
51 | for (int i = 0; i < block.getSeq().length(); i++) {
52 | seq.addInstruction(block.getSeq().getInstr(i).clone(), -1);
53 | }
54 |
55 | return new BasicBlockStatement(new BasicBlock(id, seq));
56 | }
57 |
58 | public BasicBlock getBlock() {
59 | return block;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/code/cfg/ExceptionRangeCFG.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.code.cfg;
3 |
4 | import org.jetbrains.java.decompiler.main.DecompilerContext;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 | import java.util.stream.Collectors;
9 |
10 | public class ExceptionRangeCFG {
11 | private final List protectedRange; // FIXME: replace with set
12 | private BasicBlock handler;
13 | private List exceptionTypes;
14 |
15 | public ExceptionRangeCFG(List protectedRange, BasicBlock handler, List exceptionType) {
16 | this.protectedRange = protectedRange;
17 | this.handler = handler;
18 |
19 | if (exceptionType != null) {
20 | this.exceptionTypes = new ArrayList<>(exceptionType);
21 | }
22 | }
23 |
24 | public boolean isCircular() {
25 | return protectedRange.contains(handler);
26 | }
27 |
28 | @Override
29 | public String toString() {
30 | String new_line_separator = DecompilerContext.getNewLineSeparator();
31 | StringBuilder buf = new StringBuilder();
32 |
33 | buf.append("exceptionType:");
34 |
35 | if (exceptionTypes == null) {
36 | buf.append(" null");
37 | }
38 | else {
39 | for (String exception_type : exceptionTypes) {
40 | buf.append(" ").append(exception_type);
41 | }
42 | }
43 |
44 | buf.append(new_line_separator);
45 |
46 | buf.append("handler: ").append(handler.id).append(new_line_separator);
47 | buf.append("range: ");
48 | for (BasicBlock block : protectedRange) {
49 | buf.append(block.id).append(" ");
50 | }
51 | buf.append(new_line_separator);
52 |
53 | return buf.toString();
54 | }
55 |
56 | public BasicBlock getHandler() {
57 | return handler;
58 | }
59 |
60 | public void setHandler(BasicBlock handler) {
61 | this.handler = handler;
62 | }
63 |
64 | public List getProtectedRange() {
65 | return protectedRange;
66 | }
67 |
68 | public List getExceptionTypes() {
69 | return this.exceptionTypes;
70 | }
71 |
72 | public void addExceptionType(String exceptionType) {
73 | if (this.exceptionTypes == null) {
74 | return;
75 | }
76 |
77 | if (exceptionType == null) {
78 | this.exceptionTypes = null;
79 | }
80 | else {
81 | this.exceptionTypes.add(exceptionType);
82 | }
83 | }
84 |
85 | public String getUniqueExceptionsString() {
86 | return exceptionTypes != null ? exceptionTypes.stream().distinct().collect(Collectors.joining(":")) : null;
87 | }
88 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/main/decompiler/PrintStreamLogger.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.main.decompiler;
3 |
4 | import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
5 | import org.jetbrains.java.decompiler.util.TextUtil;
6 |
7 | import java.io.PrintStream;
8 |
9 | public class PrintStreamLogger extends IFernflowerLogger {
10 |
11 | private final PrintStream stream;
12 | private int indent;
13 |
14 | public PrintStreamLogger(PrintStream printStream) {
15 | stream = printStream;
16 | indent = 0;
17 | }
18 |
19 | @Override
20 | public void writeMessage(String message, Severity severity) {
21 | if (accepts(severity)) {
22 | stream.println(severity.prefix + TextUtil.getIndentString(indent) + message);
23 | }
24 | }
25 |
26 | @Override
27 | public void writeMessage(String message, Severity severity, Throwable t) {
28 | if (accepts(severity)) {
29 | writeMessage(message, severity);
30 | t.printStackTrace(stream);
31 | }
32 | }
33 |
34 | @Override
35 | public void startReadingClass(String className) {
36 | if (accepts(Severity.INFO)) {
37 | writeMessage("Decompiling class " + className, Severity.INFO);
38 | ++indent;
39 | }
40 | }
41 |
42 | @Override
43 | public void endReadingClass() {
44 | if (accepts(Severity.INFO)) {
45 | --indent;
46 | writeMessage("... done", Severity.INFO);
47 | }
48 | }
49 |
50 | @Override
51 | public void startClass(String className) {
52 | if (accepts(Severity.INFO)) {
53 | writeMessage("Processing class " + className, Severity.TRACE);
54 | ++indent;
55 | }
56 | }
57 |
58 | @Override
59 | public void endClass() {
60 | if (accepts(Severity.INFO)) {
61 | --indent;
62 | writeMessage("... proceeded", Severity.TRACE);
63 | }
64 | }
65 |
66 | @Override
67 | public void startMethod(String methodName) {
68 | if (accepts(Severity.INFO)) {
69 | writeMessage("Processing method " + methodName, Severity.TRACE);
70 | ++indent;
71 | }
72 | }
73 |
74 | @Override
75 | public void endMethod() {
76 | if (accepts(Severity.INFO)) {
77 | --indent;
78 | writeMessage("... proceeded", Severity.TRACE);
79 | }
80 | }
81 |
82 | @Override
83 | public void startWriteClass(String className) {
84 | if (accepts(Severity.INFO)) {
85 | writeMessage("Writing class " + className, Severity.TRACE);
86 | ++indent;
87 | }
88 | }
89 |
90 | @Override
91 | public void endWriteClass() {
92 | if (accepts(Severity.INFO)) {
93 | --indent;
94 | writeMessage("... written", Severity.TRACE);
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/main/EnumProcessor.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.main;
3 |
4 | import org.jetbrains.java.decompiler.code.CodeConstants;
5 | import org.jetbrains.java.decompiler.main.rels.ClassWrapper;
6 | import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
7 | import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
8 | import org.jetbrains.java.decompiler.modules.decompiler.exps.InvocationExprent;
9 | import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
10 | import org.jetbrains.java.decompiler.modules.decompiler.stats.Statements;
11 | import org.jetbrains.java.decompiler.struct.StructClass;
12 | import org.jetbrains.java.decompiler.struct.StructField;
13 | import org.jetbrains.java.decompiler.struct.StructMethod;
14 | import org.jetbrains.java.decompiler.util.InterpreterUtil;
15 |
16 | public final class EnumProcessor {
17 | public static void clearEnum(ClassWrapper wrapper) {
18 | StructClass cl = wrapper.getClassStruct();
19 |
20 | // hide values/valueOf methods and super() invocations
21 | for (MethodWrapper method : wrapper.getMethods()) {
22 | StructMethod mt = method.methodStruct;
23 | String name = mt.getName();
24 | String descriptor = mt.getDescriptor();
25 |
26 | if ("values".equals(name)) {
27 | if (descriptor.equals("()[L" + cl.qualifiedName + ";")) {
28 | wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(name, descriptor));
29 | }
30 | }
31 | else if ("valueOf".equals(name)) {
32 | if (descriptor.equals("(Ljava/lang/String;)L" + cl.qualifiedName + ";")) {
33 | wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(name, descriptor));
34 | }
35 | }
36 | else if (CodeConstants.INIT_NAME.equals(name)) {
37 | Statement firstData = Statements.findFirstData(method.root);
38 | if (firstData != null && !firstData.getExprents().isEmpty()) {
39 | Exprent exprent = firstData.getExprents().get(0);
40 | if (exprent.type == Exprent.EXPRENT_INVOCATION) {
41 | InvocationExprent invExpr = (InvocationExprent)exprent;
42 | if (Statements.isInvocationInitConstructor(invExpr, method, wrapper, false)) {
43 | firstData.getExprents().remove(0);
44 | }
45 | }
46 | }
47 | }
48 | }
49 |
50 | // hide synthetic fields of enum and it's constants
51 | for (StructField fd : cl.getFields()) {
52 | String descriptor = fd.getDescriptor();
53 | if (fd.isSynthetic() && descriptor.equals("[L" + cl.qualifiedName + ";")) {
54 | wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(fd.getName(), descriptor));
55 | }
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/struct/consts/LinkConstant.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package org.jetbrains.java.decompiler.struct.consts;
3 |
4 | public class LinkConstant extends PooledConstant {
5 | public int index1, index2;
6 | public String classname;
7 | public String elementname;
8 | public String descriptor;
9 |
10 | public LinkConstant(int type, String classname, String elementname, String descriptor) {
11 | super(type);
12 | this.classname = classname;
13 | this.elementname = elementname;
14 | this.descriptor = descriptor;
15 |
16 | initConstant();
17 | }
18 |
19 | public LinkConstant(int type, int index1, int index2) {
20 | super(type);
21 | this.index1 = index1;
22 | this.index2 = index2;
23 | }
24 |
25 | private void initConstant() {
26 | if (type == CONSTANT_Methodref ||
27 | type == CONSTANT_InterfaceMethodref ||
28 | type == CONSTANT_InvokeDynamic ||
29 | (type == CONSTANT_MethodHandle && index1 != CONSTANT_MethodHandle_REF_getField && index1 != CONSTANT_MethodHandle_REF_putField)) {
30 | int parenth = descriptor.indexOf(')');
31 | if (descriptor.length() < 2 || parenth < 0 || descriptor.charAt(0) != '(') {
32 | throw new IllegalArgumentException("Invalid descriptor: " + descriptor +
33 | "; type = " + type + "; classname = " + classname + "; elementname = " + elementname);
34 | }
35 | }
36 | }
37 |
38 | @Override
39 | public void resolveConstant(ConstantPool pool) {
40 | if (type == CONSTANT_NameAndType) {
41 | elementname = pool.getPrimitiveConstant(index1).getString();
42 | descriptor = pool.getPrimitiveConstant(index2).getString();
43 | }
44 | else if (type == CONSTANT_MethodHandle) {
45 | LinkConstant ref_info = pool.getLinkConstant(index2);
46 |
47 | classname = ref_info.classname;
48 | elementname = ref_info.elementname;
49 | descriptor = ref_info.descriptor;
50 | }
51 | else {
52 | if (type != CONSTANT_InvokeDynamic && type != CONSTANT_Dynamic) {
53 | classname = pool.getPrimitiveConstant(index1).getString();
54 | }
55 |
56 | LinkConstant nametype = pool.getLinkConstant(index2);
57 | elementname = nametype.elementname;
58 | descriptor = nametype.descriptor;
59 | }
60 |
61 | initConstant();
62 | }
63 |
64 | @Override
65 | public boolean equals(Object o) {
66 | if (o == this) return true;
67 | if (!(o instanceof LinkConstant cn)) return false;
68 |
69 | return this.type == cn.type &&
70 | this.elementname.equals(cn.elementname) &&
71 | this.descriptor.equals(cn.descriptor) &&
72 | (this.type != CONSTANT_NameAndType || this.classname.equals(cn.classname));
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/org/jetbrains/java/decompiler/util/InterpreterUtil.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
2 | package org.jetbrains.java.decompiler.util;
3 |
4 | import java.io.*;
5 | import java.util.Collection;
6 | import java.util.HashSet;
7 | import java.util.zip.ZipEntry;
8 | import java.util.zip.ZipFile;
9 |
10 | public final class InterpreterUtil {
11 | public static final boolean IS_WINDOWS = System.getProperty("os.name", "").startsWith("Windows");
12 |
13 | public static final int[] EMPTY_INT_ARRAY = new int[0];
14 |
15 | private static final int BUFFER_SIZE = 16 * 1024;
16 |
17 | public static void copyFile(File source, File target) throws IOException {
18 | try (FileInputStream in = new FileInputStream(source); FileOutputStream out = new FileOutputStream(target)) {
19 | copyStream(in, out);
20 | }
21 | }
22 |
23 | public static void copyStream(InputStream in, OutputStream out) throws IOException {
24 | byte[] buffer = new byte[BUFFER_SIZE];
25 | int len;
26 | while ((len = in.read(buffer)) >= 0) {
27 | out.write(buffer, 0, len);
28 | }
29 | }
30 |
31 | public static byte[] getBytes(ZipFile archive, ZipEntry entry) throws IOException {
32 | try (InputStream stream = archive.getInputStream(entry)) {
33 | return readBytes(stream, (int)entry.getSize());
34 | }
35 | }
36 |
37 | public static byte[] getBytes(File file) throws IOException {
38 | try (FileInputStream stream = new FileInputStream(file)) {
39 | return readBytes(stream, (int)file.length());
40 | }
41 | }
42 |
43 | public static byte[] readBytes(InputStream stream, int length) throws IOException {
44 | byte[] bytes = new byte[length];
45 |
46 | int n = 0, off = 0;
47 | while (n < length) {
48 | int count = stream.read(bytes, off + n, length - n);
49 | if (count < 0) {
50 | throw new IOException("premature end of stream");
51 | }
52 | n += count;
53 | }
54 |
55 | return bytes;
56 | }
57 |
58 | public static void discardBytes(InputStream stream, int length) throws IOException {
59 | if (stream.skip(length) != length) {
60 | throw new IOException("premature end of stream");
61 | }
62 | }
63 |
64 | public static boolean equalSets(Collection> c1, Collection> c2) {
65 | if (c1 == null) {
66 | return c2 == null;
67 | }
68 | else if (c2 == null) {
69 | return false;
70 | }
71 |
72 | if (c1.size() != c2.size()) {
73 | return false;
74 | }
75 |
76 | HashSet