mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-01 06:51:17 +07:00
[java-decompiler] IJ-CR-18502 Don't decompile common constant variables in own declaration
Prevents variables from referencing themselves, for example: `public static final int MIN_VALUE = MIN_VALUE` in `java.lang.Integer`. GitOrigin-RevId: b415924b4bb752f5b47e5191d6b65d9416f88117
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a415b77d56
commit
7cfa69cd39
+2
-2
@@ -1,4 +1,4 @@
|
||||
// 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.
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.java.decompiler.main;
|
||||
|
||||
import org.jetbrains.java.decompiler.code.CodeConstants;
|
||||
@@ -614,7 +614,7 @@ public class ClassWriter {
|
||||
if (attr != null) {
|
||||
PrimitiveConstant constant = cl.getPool().getPrimitiveConstant(attr.getIndex());
|
||||
buffer.append(" = ");
|
||||
buffer.append(new ConstExprent(fieldType, constant.value, null).toJava(indent, tracer));
|
||||
buffer.append(new ConstExprent(fieldType, constant.value, null, fd).toJava(indent, tracer));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+71
-40
@@ -2,10 +2,13 @@
|
||||
package org.jetbrains.java.decompiler.modules.decompiler.exps;
|
||||
|
||||
import org.jetbrains.java.decompiler.code.CodeConstants;
|
||||
import org.jetbrains.java.decompiler.main.ClassesProcessor;
|
||||
import org.jetbrains.java.decompiler.main.DecompilerContext;
|
||||
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
|
||||
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
|
||||
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
|
||||
import org.jetbrains.java.decompiler.struct.StructField;
|
||||
import org.jetbrains.java.decompiler.struct.StructMember;
|
||||
import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor;
|
||||
import org.jetbrains.java.decompiler.struct.gen.VarType;
|
||||
import org.jetbrains.java.decompiler.struct.match.MatchEngine;
|
||||
@@ -22,6 +25,21 @@ import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
public class ConstExprent extends Exprent {
|
||||
private static final String SHORT_SIG = "java/lang/Short";
|
||||
private static final String INT_SIG = "java/lang/Integer";
|
||||
private static final String LONG_SIG = "java/lang/Long";
|
||||
private static final String FLOAT_SIG = "java/lang/Float";
|
||||
private static final String DOUBLE_SIG = "java/lang/Double";
|
||||
private static final String MATH_SIG = "java/lang/Math";
|
||||
private static final String MIN_VAL = "MIN_VALUE";
|
||||
private static final String MAX_VAL = "MAX_VALUE";
|
||||
private static final String POS_INF = "POSITIVE_INFINITY";
|
||||
private static final String NEG_INF = "NEGATIVE_INFINITY";
|
||||
private static final String NAN = "NaN";
|
||||
private static final String MIN_NORM = "MIN_NORMAL";
|
||||
private static final String E = "E";
|
||||
private static final String PI = "PI";
|
||||
|
||||
private static final Map<Integer, String> CHAR_ESCAPES = Map.of(
|
||||
0x8, "\\b", /* \u0008: backspace BS */
|
||||
0x9, "\\t", /* \u0009: horizontal tab HT */
|
||||
@@ -32,6 +50,7 @@ public class ConstExprent extends Exprent {
|
||||
0x5C, "\\\\" /* \u005c: backslash \ */
|
||||
);
|
||||
|
||||
private StructMember parent;
|
||||
private VarType constType;
|
||||
private final Object value;
|
||||
private final boolean boolPermitted;
|
||||
@@ -44,6 +63,11 @@ public class ConstExprent extends Exprent {
|
||||
this(constType, value, false, bytecodeOffsets);
|
||||
}
|
||||
|
||||
public ConstExprent(VarType constType, Object value, Set<Integer> bytecodeOffsets, StructMember parent) {
|
||||
this(constType, value, bytecodeOffsets);
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
private ConstExprent(VarType constType, Object value, boolean boolPermitted, Set<Integer> bytecodeOffsets) {
|
||||
super(EXPRENT_CONST);
|
||||
this.constType = constType;
|
||||
@@ -135,11 +159,11 @@ public class ConstExprent extends Exprent {
|
||||
case CodeConstants.TYPE_SHORT:
|
||||
int shortVal = (Integer)value;
|
||||
if (!literal) {
|
||||
if (shortVal == Short.MAX_VALUE) {
|
||||
return new FieldExprent("MAX_VALUE", "java/lang/Short", true, null, FieldDescriptor.SHORT_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
if (shortVal == Short.MAX_VALUE && !inConstantVariable(SHORT_SIG, MAX_VAL)) {
|
||||
return new FieldExprent(MAX_VAL, SHORT_SIG, true, null, FieldDescriptor.SHORT_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
else if (shortVal == Short.MIN_VALUE) {
|
||||
return new FieldExprent("MIN_VALUE", "java/lang/Short", true, null, FieldDescriptor.SHORT_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
else if (shortVal == Short.MIN_VALUE && !inConstantVariable(SHORT_SIG, MIN_VAL)) {
|
||||
return new FieldExprent(MIN_VAL, SHORT_SIG, true, null, FieldDescriptor.SHORT_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
}
|
||||
return new TextBuffer(value.toString());
|
||||
@@ -147,11 +171,11 @@ public class ConstExprent extends Exprent {
|
||||
case CodeConstants.TYPE_INT:
|
||||
int intVal = (Integer)value;
|
||||
if (!literal) {
|
||||
if (intVal == Integer.MAX_VALUE) {
|
||||
return new FieldExprent("MAX_VALUE", "java/lang/Integer", true, null, FieldDescriptor.INTEGER_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
if (intVal == Integer.MAX_VALUE && !inConstantVariable(INT_SIG, MAX_VAL)) {
|
||||
return new FieldExprent(MAX_VAL, INT_SIG, true, null, FieldDescriptor.INTEGER_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
else if (intVal == Integer.MIN_VALUE) {
|
||||
return new FieldExprent("MIN_VALUE", "java/lang/Integer", true, null, FieldDescriptor.INTEGER_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
else if (intVal == Integer.MIN_VALUE && !inConstantVariable(INT_SIG, MIN_VAL)) {
|
||||
return new FieldExprent(MIN_VAL, INT_SIG, true, null, FieldDescriptor.INTEGER_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
}
|
||||
return new TextBuffer(value.toString());
|
||||
@@ -159,11 +183,11 @@ public class ConstExprent extends Exprent {
|
||||
case CodeConstants.TYPE_LONG:
|
||||
long longVal = (Long)value;
|
||||
if (!literal) {
|
||||
if (longVal == Long.MAX_VALUE) {
|
||||
return new FieldExprent("MAX_VALUE", "java/lang/Long", true, null, FieldDescriptor.LONG_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
if (longVal == Long.MAX_VALUE && !inConstantVariable(LONG_SIG, MAX_VAL)) {
|
||||
return new FieldExprent(MAX_VAL, LONG_SIG, true, null, FieldDescriptor.LONG_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
else if (longVal == Long.MIN_VALUE) {
|
||||
return new FieldExprent("MIN_VALUE", "java/lang/Long", true, null, FieldDescriptor.LONG_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
else if (longVal == Long.MIN_VALUE && !inConstantVariable(LONG_SIG, MIN_VAL)) {
|
||||
return new FieldExprent(MIN_VAL, LONG_SIG, true, null, FieldDescriptor.LONG_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
}
|
||||
return new TextBuffer(value.toString()).append('L');
|
||||
@@ -171,23 +195,23 @@ public class ConstExprent extends Exprent {
|
||||
case CodeConstants.TYPE_FLOAT:
|
||||
float floatVal = (Float)value;
|
||||
if (!literal) {
|
||||
if (Float.isNaN(floatVal)) {
|
||||
return new FieldExprent("NaN", "java/lang/Float", true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
if (Float.isNaN(floatVal) && !inConstantVariable(FLOAT_SIG, NAN)) {
|
||||
return new FieldExprent(NAN, FLOAT_SIG, true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
else if (floatVal == Float.POSITIVE_INFINITY) {
|
||||
return new FieldExprent("POSITIVE_INFINITY", "java/lang/Float", true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
else if (floatVal == Float.POSITIVE_INFINITY && !inConstantVariable(FLOAT_SIG, POS_INF)) {
|
||||
return new FieldExprent(POS_INF, FLOAT_SIG, true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
else if (floatVal == Float.NEGATIVE_INFINITY) {
|
||||
return new FieldExprent("NEGATIVE_INFINITY", "java/lang/Float", true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
else if (floatVal == Float.NEGATIVE_INFINITY && !inConstantVariable(FLOAT_SIG, NEG_INF)) {
|
||||
return new FieldExprent(NEG_INF, FLOAT_SIG, true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
else if (floatVal == Float.MAX_VALUE) {
|
||||
return new FieldExprent("MAX_VALUE", "java/lang/Float", true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
else if (floatVal == Float.MAX_VALUE && !inConstantVariable(FLOAT_SIG, MAX_VAL)) {
|
||||
return new FieldExprent(MAX_VAL, FLOAT_SIG, true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
else if (floatVal == Float.MIN_VALUE) {
|
||||
return new FieldExprent("MIN_VALUE", "java/lang/Float", true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
else if (floatVal == Float.MIN_VALUE && !inConstantVariable(FLOAT_SIG, MIN_VAL)) {
|
||||
return new FieldExprent(MIN_VAL, FLOAT_SIG, true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
else if (floatVal == Float.MIN_NORMAL) {
|
||||
return new FieldExprent("MIN_NORMAL", "java/lang/Float", true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
else if (floatVal == Float.MIN_NORMAL && !inConstantVariable(FLOAT_SIG, MIN_NORM)) {
|
||||
return new FieldExprent(MIN_NORM, FLOAT_SIG, true, null, FieldDescriptor.FLOAT_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
}
|
||||
else if (Float.isNaN(floatVal)) {
|
||||
@@ -204,29 +228,29 @@ public class ConstExprent extends Exprent {
|
||||
case CodeConstants.TYPE_DOUBLE:
|
||||
double doubleVal = (Double)value;
|
||||
if (!literal) {
|
||||
if (Double.isNaN(doubleVal)) {
|
||||
return new FieldExprent("NaN", "java/lang/Double", true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
if (Double.isNaN(doubleVal) && !inConstantVariable(DOUBLE_SIG, NAN)) {
|
||||
return new FieldExprent(NAN, DOUBLE_SIG, true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
else if (doubleVal == Double.POSITIVE_INFINITY) {
|
||||
return new FieldExprent("POSITIVE_INFINITY", "java/lang/Double", true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
else if (doubleVal == Double.POSITIVE_INFINITY && !inConstantVariable(DOUBLE_SIG, POS_INF)) {
|
||||
return new FieldExprent(POS_INF, DOUBLE_SIG, true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
else if (doubleVal == Double.NEGATIVE_INFINITY) {
|
||||
return new FieldExprent("NEGATIVE_INFINITY", "java/lang/Double", true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
else if (doubleVal == Double.NEGATIVE_INFINITY && !inConstantVariable(DOUBLE_SIG, NEG_INF)) {
|
||||
return new FieldExprent(NEG_INF, DOUBLE_SIG, true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
else if (doubleVal == Double.MAX_VALUE) {
|
||||
return new FieldExprent("MAX_VALUE", "java/lang/Double", true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
else if (doubleVal == Double.MAX_VALUE && !inConstantVariable(DOUBLE_SIG, MAX_VAL)) {
|
||||
return new FieldExprent(MAX_VAL, DOUBLE_SIG, true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
else if (doubleVal == Double.MIN_VALUE) {
|
||||
return new FieldExprent("MIN_VALUE", "java/lang/Double", true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
else if (doubleVal == Double.MIN_VALUE && !inConstantVariable(DOUBLE_SIG, MIN_VAL)) {
|
||||
return new FieldExprent(MIN_VAL, DOUBLE_SIG, true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
else if (doubleVal == Double.MIN_NORMAL) {
|
||||
return new FieldExprent("MIN_NORMAL", "java/lang/Double", true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
else if (doubleVal == Double.MIN_NORMAL && !inConstantVariable(DOUBLE_SIG, MIN_NORM)) {
|
||||
return new FieldExprent(MIN_NORM, DOUBLE_SIG, true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
else if (doubleVal == Math.E) {
|
||||
return new FieldExprent("E", "java/lang/Math", true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
else if (doubleVal == Math.E && !inConstantVariable(MATH_SIG, E)) {
|
||||
return new FieldExprent(E, MATH_SIG, true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
else if (doubleVal == Math.PI) {
|
||||
return new FieldExprent("PI", "java/lang/Math", true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
else if (doubleVal == Math.PI && !inConstantVariable(MATH_SIG, PI)) {
|
||||
return new FieldExprent(PI, MATH_SIG, true, null, FieldDescriptor.DOUBLE_DESCRIPTOR, bytecode).toJava(0, tracer);
|
||||
}
|
||||
}
|
||||
else if (Double.isNaN(doubleVal)) {
|
||||
@@ -257,6 +281,13 @@ public class ConstExprent extends Exprent {
|
||||
throw new RuntimeException("invalid constant type: " + constType);
|
||||
}
|
||||
|
||||
private boolean inConstantVariable(String classSignature, String variableName) {
|
||||
ClassesProcessor.ClassNode node = (ClassesProcessor.ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
|
||||
return node.classStruct.qualifiedName.equals(classSignature) &&
|
||||
parent instanceof StructField &&
|
||||
((StructField)parent).getName().equals(variableName);
|
||||
}
|
||||
|
||||
public boolean isNull() {
|
||||
return CodeConstants.TYPE_NULL == constType.type;
|
||||
}
|
||||
|
||||
+5
-1
@@ -1,4 +1,4 @@
|
||||
// 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.
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.java.decompiler;
|
||||
|
||||
import org.jetbrains.java.decompiler.main.DecompilerContext;
|
||||
@@ -65,6 +65,10 @@ public class SingleClassesTest {
|
||||
DecompilerContext.setProperty(IFernflowerPreferences.LITERALS_AS_IS, "0");
|
||||
doTest("pkg/TestConstants");
|
||||
}
|
||||
@Test public void testInteger() {
|
||||
DecompilerContext.setProperty(IFernflowerPreferences.LITERALS_AS_IS, "0");
|
||||
doTest("java/lang/Integer");
|
||||
}
|
||||
@Test public void testEnum() { doTest("pkg/TestEnum"); }
|
||||
@Test public void testDebugSymbols() { doTest("pkg/TestDebugSymbols"); }
|
||||
@Test public void testInvalidMethodSignature() { doTest("InvalidMethodSignature"); }
|
||||
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user