Skip to content

Commit

Permalink
Add string concatenation in Java 9 support
Browse files Browse the repository at this point in the history
  • Loading branch information
emmanue1 committed Jun 16, 2019
1 parent cdb695a commit 16619db
Show file tree
Hide file tree
Showing 11 changed files with 240 additions and 165 deletions.
30 changes: 15 additions & 15 deletions src/main/java/org/jd/core/v1/api/printer/Printer.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@


public interface Printer {
int UNKNOWN_LINE_NUMBER = 0;
void start(int maxLineNumber, int majorVersion, int minorVersion);
void end();

void printText(String text);
void printNumericConstant(String constant);
void printStringConstant(String constant, String ownerInternalName);
void printKeyword(String keyword);

// Declaration & reference types
int TYPE = 1;
Expand All @@ -19,30 +25,24 @@ public interface Printer {
int PACKAGE = 5;
int MODULE = 6;

// Marker types
int COMMENT = 1;
int JAVADOC = 2;
int ERROR = 3;
int IMPORT_STATEMENTS = 4;

void start(int maxLineNumber, int majorVersion, int minorVersion);
void end();

void printText(String text);
void printNumericConstant(String constant);
void printStringConstant(String constant, String ownerInternalName);
void printKeyword(String keyword);

void printDeclaration(int type, String internalTypeName, String name, String descriptor);
void printReference(int type, String internalTypeName, String name, String descriptor, String ownerInternalName);

void indent();
void unindent();

int UNKNOWN_LINE_NUMBER = 0;

void startLine(int lineNumber);
void endLine();
void extraLine(int count);

// Marker types
int COMMENT = 1;
int JAVADOC = 2;
int ERROR = 3;
int IMPORT_STATEMENTS = 4;

void startMarker(int type);
void endMarker(int type);
}
10 changes: 8 additions & 2 deletions src/main/java/org/jd/core/v1/model/classfile/ConstantPool.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,19 @@ public <T extends Constant> T getConstant(int index) {
return (T)constants[index];
}

public String getConstantTypeName(int classIndex) {
ConstantClass cc = (ConstantClass)constants[classIndex];
public String getConstantTypeName(int index) {
ConstantClass cc = (ConstantClass)constants[index];
ConstantUtf8 cutf8 = (ConstantUtf8)constants[cc.getNameIndex()];
return cutf8.getValue();
}

public String getConstantString(int index) {
ConstantString cString = (ConstantString)constants[index];
ConstantUtf8 cutf8 = (ConstantUtf8)constants[cString.getStringIndex()];
return cutf8.getValue();
}

public String getConstantUtf8(int index) {
ConstantUtf8 cutf8 = (ConstantUtf8)constants[index];
return cutf8.getValue();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import org.jd.core.v1.model.javasyntax.type.Type;

public class StringConstantExpression extends AbstractLineNumberExpression {
public static final StringConstantExpression EMPTY_STRING = new StringConstantExpression("");

protected String string;

public StringConstantExpression(String string) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -727,8 +727,8 @@ public void parse(BasicBlock basicBlock, Statements<Statement> statements, Defau
typeName = constants.getConstantTypeName(constantMemberRef.getClassIndex());
ot = objectTypeMaker.make(typeName);
constantNameAndType = constants.getConstant(constantMemberRef.getNameAndTypeIndex());
name = constants.getConstantString(constantNameAndType.getNameIndex());
descriptor = constants.getConstantString(constantNameAndType.getDescriptorIndex());
name = constants.getConstantUtf8(constantNameAndType.getNameIndex());
descriptor = constants.getConstantUtf8(constantNameAndType.getDescriptorIndex());
BaseExpression parameters = getParameters(statements, stack, descriptor);
Type returnedType = signatureParser.parseReturnedType(descriptor);

Expand Down Expand Up @@ -777,7 +777,7 @@ public void parse(BasicBlock basicBlock, Statements<Statement> statements, Defau
"toString".equals(name) && "()Ljava/lang/String;".equals(descriptor)) {
typeName = constants.getConstantTypeName(constantMemberRef.getClassIndex());
if ("java/lang/StringBuilder".equals(typeName) || "java/lang/StringBuffer".equals(typeName)) {
stack.push(CreateConcatStringUtil.create(expression1, lineNumber, typeName));
stack.push(StringConcatenationUtil.create(expression1, lineNumber, typeName));
break;
}
}
Expand Down Expand Up @@ -1043,7 +1043,7 @@ private void parseLDC(DefaultStack<Expression> stack, ConstantPool constants, in
break;
case Constant.CONSTANT_String:
int stringIndex = ((ConstantString)constant).getStringIndex();
stack.push(new StringConstantExpression(lineNumber, constants.getConstantString(stringIndex)));
stack.push(new StringConstantExpression(lineNumber, constants.getConstantUtf8(stringIndex)));
break;
}
}
Expand Down Expand Up @@ -1273,27 +1273,39 @@ private void parseInvokeDynamic(Statements<Statement> statements, DefaultStack<E
}
}

// Create lambda expression
// Create expression
ConstantMemberRef constantMemberRef = constants.getConstant(index);

ConstantNameAndType indyCnat = constants.getConstant(constantMemberRef.getNameAndTypeIndex());
//String indyMethodName = constants.getConstantString(indyCnat.getNameIndex());
String indyDescriptor = constants.getConstantString(indyCnat.getDescriptorIndex());
String indyMethodName = constants.getConstantUtf8(indyCnat.getNameIndex());
String indyDescriptor = constants.getConstantUtf8(indyCnat.getDescriptorIndex());
BaseExpression indyParameters = getParameters(statements, stack, indyDescriptor);
Type indyType = signatureParser.parseReturnedType(indyDescriptor);

BootstrapMethod bootstrapMethod = attributeBootstrapMethods.getBootstrapMethods()[constantMemberRef.getClassIndex()];
int[] bootstrapArguments = bootstrapMethod.getBootstrapArguments();

if ("makeConcatWithConstants".equals(indyMethodName)) {
// Create Java 9+ string concatenation
String recipe = constants.getConstantString(bootstrapArguments[0]);
stack.push(StringConcatenationUtil.create(recipe, indyParameters));
return;
} else if ("makeConcat".equals(indyMethodName)) {
// Create Java 9+ string concatenation
stack.push(StringConcatenationUtil.create(indyParameters));
return;
}

ConstantMethodType cmt0 = constants.getConstant(bootstrapArguments[0]);
String descriptor0 = constants.getConstantString(cmt0.getDescriptorIndex());
String descriptor0 = constants.getConstantUtf8(cmt0.getDescriptorIndex());
Type returnedType = signatureParser.parseReturnedType(descriptor0);
int parameterCount = signatureParser.parseParameterTypes(descriptor0).size();
ConstantMethodHandle constantMethodHandle1 = constants.getConstant(bootstrapArguments[1]);
ConstantMemberRef cmr1 = constants.getConstant(constantMethodHandle1.getReferenceIndex());
String typeName = constants.getConstantTypeName(cmr1.getClassIndex());
ConstantNameAndType cnat1 = constants.getConstant(cmr1.getNameAndTypeIndex());
String name1 = constants.getConstantString(cnat1.getNameIndex());
String descriptor1 = constants.getConstantString(cnat1.getDescriptorIndex());
String name1 = constants.getConstantUtf8(cnat1.getNameIndex());
String descriptor1 = constants.getConstantUtf8(cnat1.getDescriptorIndex());

if (typeName.equals(internalTypeName)) {
for (ClassFileConstructorOrMethodDeclaration methodDeclaration : bodyDeclaration.getMethodDeclarations()) {
Expand Down Expand Up @@ -1637,7 +1649,7 @@ private void parseGetStatic(DefaultStack<Expression> stack, ConstantPool constan
ConstantMemberRef constantMemberRef = constants.getConstant(index);
String typeName = constants.getConstantTypeName(constantMemberRef.getClassIndex());
ConstantNameAndType constantNameAndType = constants.getConstant(constantMemberRef.getNameAndTypeIndex());
String name = constants.getConstantString(constantNameAndType.getNameIndex());
String name = constants.getConstantUtf8(constantNameAndType.getNameIndex());

if (name.equals("TYPE") && typeName.startsWith("java/lang/")) {
switch (typeName) {
Expand All @@ -1653,7 +1665,7 @@ private void parseGetStatic(DefaultStack<Expression> stack, ConstantPool constan
}
}

String descriptor = constants.getConstantString(constantNameAndType.getDescriptorIndex());
String descriptor = constants.getConstantUtf8(constantNameAndType.getDescriptorIndex());
Type type = signatureParser.parseTypeSignature(descriptor);
ObjectType ot = objectTypeMaker.make(typeName);
Expression objectRef = new ObjectTypeReferenceExpression(lineNumber, ot, !internalTypeName.equals(typeName) || localVariableMaker.containsName(name));
Expand All @@ -1665,8 +1677,8 @@ private void parsePutStatic(Statements statements, DefaultStack<Expression> stac
String typeName = constants.getConstantTypeName(constantMemberRef.getClassIndex());
ObjectType ot = objectTypeMaker.make(typeName);
ConstantNameAndType constantNameAndType = constants.getConstant(constantMemberRef.getNameAndTypeIndex());
String name = constants.getConstantString(constantNameAndType.getNameIndex());
String descriptor = constants.getConstantString(constantNameAndType.getDescriptorIndex());
String name = constants.getConstantUtf8(constantNameAndType.getNameIndex());
String descriptor = constants.getConstantUtf8(constantNameAndType.getDescriptorIndex());
Type type = signatureParser.parseTypeSignature(descriptor);
Expression valueRef = stack.pop();
Expression objectRef = new ObjectTypeReferenceExpression(lineNumber, ot, !internalTypeName.equals(typeName) || localVariableMaker.containsName(name));
Expand All @@ -1679,8 +1691,8 @@ private void parseGetField(DefaultStack<Expression> stack, ConstantPool constant
String typeName = constants.getConstantTypeName(constantMemberRef.getClassIndex());
ObjectType ot = objectTypeMaker.make(typeName);
ConstantNameAndType constantNameAndType = constants.getConstant(constantMemberRef.getNameAndTypeIndex());
String name = constants.getConstantString(constantNameAndType.getNameIndex());
String descriptor = constants.getConstantString(constantNameAndType.getDescriptorIndex());
String name = constants.getConstantUtf8(constantNameAndType.getNameIndex());
String descriptor = constants.getConstantUtf8(constantNameAndType.getDescriptorIndex());
Type type = signatureParser.parseTypeSignature(descriptor);
Expression objectRef = stack.pop();
stack.push(new FieldReferenceExpression(lineNumber, type, getFieldInstanceReference(objectRef, ot, name), typeName, name, descriptor));
Expand All @@ -1691,8 +1703,8 @@ private void parsePutField(Statements statements, DefaultStack<Expression> stack
String typeName = constants.getConstantTypeName(constantMemberRef.getClassIndex());
ObjectType ot = objectTypeMaker.make(typeName);
ConstantNameAndType constantNameAndType = constants.getConstant(constantMemberRef.getNameAndTypeIndex());
String name = constants.getConstantString(constantNameAndType.getNameIndex());
String descriptor = constants.getConstantString(constantNameAndType.getDescriptorIndex());
String name = constants.getConstantUtf8(constantNameAndType.getNameIndex());
String descriptor = constants.getConstantUtf8(constantNameAndType.getDescriptorIndex());
Type type = signatureParser.parseTypeSignature(descriptor);
Expression valueRef = stack.pop();
Expression objectRef = stack.pop();
Expand Down Expand Up @@ -1942,12 +1954,12 @@ public static boolean isAssertCondition(String internalTypeName, BasicBlock basi
ConstantPool constants = method.getConstants();
ConstantMemberRef constantMemberRef = constants.getConstant( ((code[++offset] & 255) << 8) | (code[++offset] & 255) );
ConstantNameAndType constantNameAndType = constants.getConstant(constantMemberRef.getNameAndTypeIndex());
String name = constants.getConstantString(constantNameAndType.getNameIndex());
String name = constants.getConstantUtf8(constantNameAndType.getNameIndex());

if (! "$assertionsDisabled".equals(name))
return false;

String descriptor = constants.getConstantString(constantNameAndType.getDescriptorIndex());
String descriptor = constants.getConstantUtf8(constantNameAndType.getDescriptorIndex());

if (! "Z".equals(descriptor))
return false;
Expand Down Expand Up @@ -2309,7 +2321,7 @@ public static int evalStackDepth(ConstantPool constants, byte[] code, BasicBlock
case 182: case 183: // INVOKEVIRTUAL, INVOKESPECIAL
constantMemberRef = constants.getConstant(((code[++offset] & 255) << 8) | (code[++offset] & 255));
constantNameAndType = constants.getConstant(constantMemberRef.getNameAndTypeIndex());
descriptor = constants.getConstantString(constantNameAndType.getDescriptorIndex());
descriptor = constants.getConstantUtf8(constantNameAndType.getDescriptorIndex());
depth -= 1 + countMethodParameters(descriptor);

if (descriptor.charAt(descriptor.length()-1) != 'V') {
Expand All @@ -2319,7 +2331,7 @@ public static int evalStackDepth(ConstantPool constants, byte[] code, BasicBlock
case 184: // INVOKESTATIC
constantMemberRef = constants.getConstant(((code[++offset] & 255) << 8) | (code[++offset] & 255));
constantNameAndType = constants.getConstant(constantMemberRef.getNameAndTypeIndex());
descriptor = constants.getConstantString(constantNameAndType.getDescriptorIndex());
descriptor = constants.getConstantUtf8(constantNameAndType.getDescriptorIndex());
depth -= countMethodParameters(descriptor);

if (descriptor.charAt(descriptor.length()-1) != 'V') {
Expand All @@ -2329,7 +2341,7 @@ public static int evalStackDepth(ConstantPool constants, byte[] code, BasicBlock
case 185: // INVOKEINTERFACE
constantMemberRef = constants.getConstant(((code[++offset] & 255) << 8) | (code[++offset] & 255));
constantNameAndType = constants.getConstant(constantMemberRef.getNameAndTypeIndex());
descriptor = constants.getConstantString(constantNameAndType.getDescriptorIndex());
descriptor = constants.getConstantUtf8(constantNameAndType.getDescriptorIndex());
depth -= 1 + countMethodParameters(descriptor);
offset += 2; // Skip 'count' and one byte

Expand All @@ -2340,7 +2352,7 @@ public static int evalStackDepth(ConstantPool constants, byte[] code, BasicBlock
case 186: // INVOKEDYNAMIC
constantMemberRef = constants.getConstant(((code[++offset] & 255) << 8) | (code[++offset] & 255));
constantNameAndType = constants.getConstant(constantMemberRef.getNameAndTypeIndex());
descriptor = constants.getConstantString(constantNameAndType.getDescriptorIndex());
descriptor = constants.getConstantUtf8(constantNameAndType.getDescriptorIndex());
depth -= countMethodParameters(descriptor);
offset += 2; // Skip 2 bytes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,24 +204,24 @@ protected static void writeByteCode(String linePrefix, StringBuilder sb, Constan
ConstantMemberRef constantMemberRef = constants.getConstant(((code[++offset] & 255) << 8) | (code[++offset] & 255));
String typeName = constants.getConstantTypeName(constantMemberRef.getClassIndex());
ConstantNameAndType constantNameAndType = constants.getConstant(constantMemberRef.getNameAndTypeIndex());
String name = constants.getConstantString(constantNameAndType.getNameIndex());
String descriptor = constants.getConstantString(constantNameAndType.getDescriptorIndex());
String name = constants.getConstantUtf8(constantNameAndType.getNameIndex());
String descriptor = constants.getConstantUtf8(constantNameAndType.getDescriptorIndex());

sb.append(" ").append(typeName).append('.').append(name).append(" : ").append(descriptor);
break;
case 180: case 181: case 182: case 183: case 184: // GETFIELD, PUTFIELD, INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC
constantMemberRef = constants.getConstant(((code[++offset] & 255) << 8) | (code[++offset] & 255));
constantNameAndType = constants.getConstant(constantMemberRef.getNameAndTypeIndex());
name = constants.getConstantString(constantNameAndType.getNameIndex());
descriptor = constants.getConstantString(constantNameAndType.getDescriptorIndex());
name = constants.getConstantUtf8(constantNameAndType.getNameIndex());
descriptor = constants.getConstantUtf8(constantNameAndType.getDescriptorIndex());

sb.append(" ").append(name).append(" : ").append(descriptor);
break;
case 185: case 186: // INVOKEINTERFACE, INVOKEDYNAMIC
constantMemberRef = constants.getConstant(((code[++offset] & 255) << 8) | (code[++offset] & 255));
constantNameAndType = constants.getConstant(constantMemberRef.getNameAndTypeIndex());
name = constants.getConstantString(constantNameAndType.getNameIndex());
descriptor = constants.getConstantString(constantNameAndType.getDescriptorIndex());
name = constants.getConstantUtf8(constantNameAndType.getNameIndex());
descriptor = constants.getConstantUtf8(constantNameAndType.getDescriptorIndex());

sb.append(" ").append(name).append(" : ").append(descriptor);

Expand Down Expand Up @@ -302,7 +302,7 @@ protected static void writeLDC(StringBuilder sb, ConstantPool constants, Constan
case Constant.CONSTANT_String:
sb.append(" '");
int stringIndex = ((ConstantString) constant).getStringIndex();
String str = constants.getConstantString(stringIndex);
String str = constants.getConstantUtf8(stringIndex);

for (char c : str.toCharArray()) {
switch (c) {
Expand Down
Loading

0 comments on commit 16619db

Please sign in to comment.