Avoid explicit array creation for vararg parameters
This commit is contained in:
committed by
Egor.Ushakov
parent
d149b53799
commit
dfd90978c9
@@ -343,14 +343,18 @@ public class InvocationExprent extends Exprent {
|
|||||||
|
|
||||||
BitSet setAmbiguousParameters = getAmbiguousParameters();
|
BitSet setAmbiguousParameters = getAmbiguousParameters();
|
||||||
|
|
||||||
|
// omit 'new Type[] {}' for the last parameter of a vararg method call
|
||||||
|
if (lstParameters.size() == descriptor.params.length && isVarArgCall()) {
|
||||||
|
Exprent lastParam = lstParameters.get(lstParameters.size() - 1);
|
||||||
|
if (lastParam.type == EXPRENT_NEW && lastParam.getExprType().arrayDim >= 1) {
|
||||||
|
((NewExprent) lastParam).setVarArgParam(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boolean firstParameter = true;
|
boolean firstParameter = true;
|
||||||
int start = isEnum ? 2 : 0;
|
int start = isEnum ? 2 : 0;
|
||||||
for (int i = start; i < lstParameters.size(); i++) {
|
for (int i = start; i < lstParameters.size(); i++) {
|
||||||
if (sigFields == null || sigFields.get(i) == null) {
|
if (sigFields == null || sigFields.get(i) == null) {
|
||||||
if (!firstParameter) {
|
|
||||||
buf.append(", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
TextBuffer buff = new TextBuffer();
|
TextBuffer buff = new TextBuffer();
|
||||||
boolean ambiguous = setAmbiguousParameters.get(i);
|
boolean ambiguous = setAmbiguousParameters.get(i);
|
||||||
|
|
||||||
@@ -361,7 +365,14 @@ public class InvocationExprent extends Exprent {
|
|||||||
}
|
}
|
||||||
// 'byte' and 'short' literals need an explicit narrowing type cast when used as a parameter
|
// 'byte' and 'short' literals need an explicit narrowing type cast when used as a parameter
|
||||||
ExprProcessor.getCastedExprent(param, descriptor.params[i], buff, indent, true, ambiguous, true, tracer);
|
ExprProcessor.getCastedExprent(param, descriptor.params[i], buff, indent, true, ambiguous, true, tracer);
|
||||||
buf.append(buff);
|
|
||||||
|
// the last "new Object[0]" in the vararg call is not printed
|
||||||
|
if (buff.length() > 0) {
|
||||||
|
if (!firstParameter) {
|
||||||
|
buf.append(", ");
|
||||||
|
}
|
||||||
|
buf.append(buff);
|
||||||
|
}
|
||||||
|
|
||||||
firstParameter = false;
|
firstParameter = false;
|
||||||
}
|
}
|
||||||
@@ -372,6 +383,20 @@ public class InvocationExprent extends Exprent {
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isVarArgCall() {
|
||||||
|
StructClass cl = DecompilerContext.getStructContext().getClass(classname);
|
||||||
|
if (cl != null) {
|
||||||
|
StructMethod mt = cl.getMethod(InterpreterUtil.makeUniqueKey(name, stringDescriptor));
|
||||||
|
if (mt != null) {
|
||||||
|
return mt.hasModifier(CodeConstants.ACC_VARARGS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO: try to check the class on the classpath
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isBoxingCall() {
|
private boolean isBoxingCall() {
|
||||||
if (isStatic && "valueOf".equals(name) && lstParameters.size() == 1) {
|
if (isStatic && "valueOf".equals(name) && lstParameters.size() == 1) {
|
||||||
int paramType = lstParameters.get(0).getExprType().type;
|
int paramType = lstParameters.get(0).getExprType().type;
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ public class NewExprent extends Exprent {
|
|||||||
private List<Exprent> lstDims = new ArrayList<>();
|
private List<Exprent> lstDims = new ArrayList<>();
|
||||||
private List<Exprent> lstArrayElements = new ArrayList<>();
|
private List<Exprent> lstArrayElements = new ArrayList<>();
|
||||||
private boolean directArrayInit;
|
private boolean directArrayInit;
|
||||||
|
private boolean isVarArgParam;
|
||||||
private boolean anonymous;
|
private boolean anonymous;
|
||||||
private boolean lambda;
|
private boolean lambda;
|
||||||
private boolean enumConst;
|
private boolean enumConst;
|
||||||
@@ -349,6 +350,30 @@ public class NewExprent extends Exprent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (isVarArgParam) {
|
||||||
|
// just print the array elements
|
||||||
|
VarType leftType = newType.decreaseArrayDim();
|
||||||
|
for (int i = 0; i < lstArrayElements.size(); i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
buf.append(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// new String[][]{{"abc"}, {"DEF"}} => new String[]{"abc"}, new String[]{"DEF"}
|
||||||
|
Exprent element = lstArrayElements.get(i);
|
||||||
|
if (element.type == EXPRENT_NEW) {
|
||||||
|
((NewExprent) element).setDirectArrayInit(false);
|
||||||
|
}
|
||||||
|
ExprProcessor.getCastedExprent(element, leftType, buf, indent, false, tracer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there is just one element of Object[] type it needs to be casted to resolve ambiguity
|
||||||
|
if (lstArrayElements.size() == 1) {
|
||||||
|
VarType elementType = lstArrayElements.get(0).getExprType();
|
||||||
|
if (elementType.type == CodeConstants.TYPE_OBJECT && elementType.value.equals("java/lang/Object") && elementType.arrayDim >= 1) {
|
||||||
|
buf.prepend("(Object)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
buf.append("new ").append(ExprProcessor.getTypeName(newType));
|
buf.append("new ").append(ExprProcessor.getTypeName(newType));
|
||||||
|
|
||||||
@@ -478,6 +503,10 @@ public class NewExprent extends Exprent {
|
|||||||
this.directArrayInit = directArrayInit;
|
this.directArrayInit = directArrayInit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setVarArgParam(boolean isVarArgParam) {
|
||||||
|
this.isVarArgParam = isVarArgParam;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isLambda() {
|
public boolean isLambda() {
|
||||||
return lambda;
|
return lambda;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class SingleClassesTest {
|
|||||||
"pkg/SharedName2", "pkg/SharedName3", "pkg/SharedName4", "pkg/NonSharedName",
|
"pkg/SharedName2", "pkg/SharedName3", "pkg/SharedName4", "pkg/NonSharedName",
|
||||||
"pkg/TestClashNameParent", "ext/TestClashNameParent","pkg/TestClashNameIface", "ext/TestClashNameIface"); }
|
"pkg/TestClashNameParent", "ext/TestClashNameParent","pkg/TestClashNameIface", "ext/TestClashNameIface"); }
|
||||||
@Test public void testSwitchOnEnum() { doTest("pkg/TestSwitchOnEnum","pkg/TestSwitchOnEnum$1");}
|
@Test public void testSwitchOnEnum() { doTest("pkg/TestSwitchOnEnum","pkg/TestSwitchOnEnum$1");}
|
||||||
|
@Test public void testVarArgCalls() { doTest("pkg/TestVarArgCalls"); }
|
||||||
|
|
||||||
private void doTest(String testFile, String... companionFiles) {
|
private void doTest(String testFile, String... companionFiles) {
|
||||||
ConsoleDecompiler decompiler = fixture.getDecompiler();
|
ConsoleDecompiler decompiler = fixture.getDecompiler();
|
||||||
|
|||||||
BIN
testData/classes/pkg/TestVarArgCalls.class
Normal file
BIN
testData/classes/pkg/TestVarArgCalls.class
Normal file
Binary file not shown.
104
testData/results/TestVarArgCalls.dec
Normal file
104
testData/results/TestVarArgCalls.dec
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package pkg;
|
||||||
|
|
||||||
|
public class TestVarArgCalls {
|
||||||
|
public void doSmth() {
|
||||||
|
this.printAll("Test");// 5
|
||||||
|
this.printAll("Test: %s", "abc");// 6
|
||||||
|
this.printAll("Test: %s - %s", "abc", "DEF");// 7
|
||||||
|
this.printComplex("Test");// 9
|
||||||
|
this.printComplex("Test: %[0]s", new String[]{"abc"});// 10
|
||||||
|
this.printComplex("Test: %[0]s - %[0]s", new String[]{"abc"}, new String[]{"DEF"});// 11
|
||||||
|
String.format("Test", new Object[0]);// 13
|
||||||
|
String.format("Test: %d", new Object[]{Integer.valueOf(123)});// 14
|
||||||
|
String.format("Test: %d - %s", new Object[]{Integer.valueOf(123), "DEF"});// 15
|
||||||
|
Object[] data = new Object[]{"Hello"};// 17
|
||||||
|
String.format("Test: %s", new Object[]{data});// 18
|
||||||
|
String.format("Test: %s", (Object[])data);// 19
|
||||||
|
}// 20
|
||||||
|
|
||||||
|
public void printAll(String fmt, String... params) {
|
||||||
|
System.out.println(String.format(fmt, (Object[])params));// 23
|
||||||
|
}// 24
|
||||||
|
|
||||||
|
public void printComplex(String fmt, String[]... params) {
|
||||||
|
System.out.println(String.format(fmt, (Object[])params));// 27
|
||||||
|
}// 28
|
||||||
|
}
|
||||||
|
|
||||||
|
class 'pkg/TestVarArgCalls' {
|
||||||
|
method 'doSmth ()V' {
|
||||||
|
1 4
|
||||||
|
7 4
|
||||||
|
b 5
|
||||||
|
13 5
|
||||||
|
16 5
|
||||||
|
1a 6
|
||||||
|
22 6
|
||||||
|
27 6
|
||||||
|
2a 6
|
||||||
|
2e 7
|
||||||
|
34 7
|
||||||
|
38 8
|
||||||
|
46 8
|
||||||
|
4a 8
|
||||||
|
4e 9
|
||||||
|
5c 9
|
||||||
|
68 9
|
||||||
|
6c 9
|
||||||
|
6f 10
|
||||||
|
71 10
|
||||||
|
75 10
|
||||||
|
79 11
|
||||||
|
81 11
|
||||||
|
83 11
|
||||||
|
87 11
|
||||||
|
8b 12
|
||||||
|
93 12
|
||||||
|
95 12
|
||||||
|
9b 12
|
||||||
|
9e 12
|
||||||
|
a8 13
|
||||||
|
ab 13
|
||||||
|
ac 14
|
||||||
|
b6 14
|
||||||
|
ba 15
|
||||||
|
bd 15
|
||||||
|
c0 15
|
||||||
|
c4 16
|
||||||
|
}
|
||||||
|
|
||||||
|
method 'printAll (Ljava/lang/String;[Ljava/lang/String;)V' {
|
||||||
|
0 19
|
||||||
|
5 19
|
||||||
|
8 19
|
||||||
|
b 19
|
||||||
|
e 20
|
||||||
|
}
|
||||||
|
|
||||||
|
method 'printComplex (Ljava/lang/String;[[Ljava/lang/String;)V' {
|
||||||
|
0 23
|
||||||
|
5 23
|
||||||
|
8 23
|
||||||
|
b 23
|
||||||
|
e 24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Lines mapping:
|
||||||
|
5 <-> 5
|
||||||
|
6 <-> 6
|
||||||
|
7 <-> 7
|
||||||
|
9 <-> 8
|
||||||
|
10 <-> 9
|
||||||
|
11 <-> 10
|
||||||
|
13 <-> 11
|
||||||
|
14 <-> 12
|
||||||
|
15 <-> 13
|
||||||
|
17 <-> 14
|
||||||
|
18 <-> 15
|
||||||
|
19 <-> 16
|
||||||
|
20 <-> 17
|
||||||
|
23 <-> 20
|
||||||
|
24 <-> 21
|
||||||
|
27 <-> 24
|
||||||
|
28 <-> 25
|
||||||
29
testData/src/pkg/TestVarArgCalls.java
Normal file
29
testData/src/pkg/TestVarArgCalls.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package pkg;
|
||||||
|
|
||||||
|
public class TestVarArgCalls {
|
||||||
|
public void doSmth() {
|
||||||
|
printAll("Test");
|
||||||
|
printAll("Test: %s", "abc");
|
||||||
|
printAll("Test: %s - %s", "abc", "DEF");
|
||||||
|
|
||||||
|
printComplex("Test");
|
||||||
|
printComplex("Test: %[0]s", new String[] { "abc" });
|
||||||
|
printComplex("Test: %[0]s - %[0]s", new String[] { "abc" }, new String[] { "DEF" });
|
||||||
|
|
||||||
|
String.format("Test");
|
||||||
|
String.format("Test: %d", 123);
|
||||||
|
String.format("Test: %d - %s", 123, "DEF");
|
||||||
|
|
||||||
|
Object[] data = { "Hello" };
|
||||||
|
String.format("Test: %s", (Object) data);
|
||||||
|
String.format("Test: %s", (Object[]) data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printAll(String fmt, String... params) {
|
||||||
|
System.out.println(String.format(fmt, (Object[]) params));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printComplex(String fmt, String[]... params) {
|
||||||
|
System.out.println(String.format(fmt, (Object[]) params));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user