Skip to content

Commit

Permalink
Merge pull request #4 from kyonRay/main
Browse files Browse the repository at this point in the history
<fix>(v3): fix v3 codeGen wrapper in arrays in struct.
  • Loading branch information
kyonRay authored Aug 24, 2022
2 parents d04715a + 2d24452 commit 5232778
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 21 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ ext {
junitVersion = '4.13.2'
commonsLang3Version = '3.12.0'

javaSDKVersion3 = "3.0.0-SNAPSHOT"
javaSDKVersion3 = "3.0.0"
javaSDKVersion2 = "2.9.1"
slf4jVersion = "1.7.32"
}
Expand All @@ -50,7 +50,7 @@ sourceSets {
// integrationTest.mustRunAfter test
allprojects {
group = 'org.fisco-bcos.code-generator'
version = '1.0.0-SNAPSHOT'
version = '1.0.0'
apply plugin: 'maven-publish'
apply plugin: 'idea'
apply plugin: 'eclipse'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,14 +299,35 @@ private String buildStructConstructorParameterDefinition(
final ABIDefinition.NamedType component = components.get(i);
stringBuilder.append(i > 0 ? "," : "");
if (useNativeJavaTypes) {
stringBuilder.append(
!component.getType().startsWith("tuple")
? "new "
+ buildTypeName(component.getType())
+ "("
+ component.getName()
+ ")"
: component.getName());
String state = "";
if (component.getType().startsWith("tuple")) {
// if struct
state = component.getName();
} else if (component.getType().endsWith("]")) {
// if list
ParameterizedTypeName typeName =
(ParameterizedTypeName) buildTypeName(component.getType());
TypeName argumentType = typeName.typeArguments.get(0);
state =
"new "
+ buildTypeName(component.getType())
+ "("
+ argumentType.toString()
+ ".class, "
+ component.getName()
+ ".stream().map("
+ argumentType
+ "::new).collect(java.util.stream.Collectors.toList())"
+ ")";
} else {
state =
"new "
+ buildTypeName(component.getType())
+ "("
+ component.getName()
+ ")";
}
stringBuilder.append(state);
} else {
stringBuilder.append(component.getName());
}
Expand Down Expand Up @@ -382,6 +403,7 @@ private List<TypeSpec> buildStructTypes(List<ABIDefinition> functionDefinitions)
+ ")");

for (ABIDefinition.NamedType component : namedType.getComponents()) {
String getValue = ".getValue()";
if (component.getType().equals("tuple")) {
final TypeName typeName = structClassNameMap.get(component.structIdentifier());
builder.addField(typeName, component.getName(), Modifier.PUBLIC);
Expand All @@ -393,6 +415,21 @@ private List<TypeSpec> buildStructTypes(List<ABIDefinition> functionDefinitions)
builder.addField(typeName, component.getName(), Modifier.PUBLIC);
constructorBuilder.addParameter(typeName, component.getName());
nativeConstructorBuilder.addParameter(typeName, component.getName());

getValue = "";
} else if (component.getType().endsWith("]")) {
final TypeName typeName = buildTypeName(component.getType());
final TypeName nativeTypeName = getNativeType(typeName);
builder.addField(nativeTypeName, component.getName(), Modifier.PUBLIC);
constructorBuilder.addParameter(typeName, component.getName());
nativeConstructorBuilder.addParameter(nativeTypeName, component.getName());

ParameterizedTypeName parameterizedTypeName = (ParameterizedTypeName) typeName;
TypeName argumentType = parameterizedTypeName.typeArguments.get(0);
getValue +=
".stream().map("
+ argumentType
+ "::getValue).collect(java.util.stream.Collectors.toList())";
} else {
final TypeName typeName = buildTypeName(component.getType());
final TypeName nativeTypeName = getNativeType(typeName);
Expand All @@ -409,7 +446,7 @@ private List<TypeSpec> buildStructTypes(List<ABIDefinition> functionDefinitions)
+ component.getName()
+ (structClassNameMap.keySet().stream()
.noneMatch(i -> i == component.structIdentifier())
? ".getValue()"
? getValue
: ""));
}

Expand Down Expand Up @@ -467,13 +504,8 @@ private List<ABIDefinition.NamedType> extractStructs(
if (!structMap.containsKey(structIdentifier)) {
structMap.put(structIdentifier, namedType);
}
extractNested(namedType).stream()
.filter(this::isStructType)
.forEach(
nestedNamedType ->
structMap.put(
nestedNamedType.structIdentifier(),
nestedNamedType));
// Note: structA in structB, structA must exist in struct map, so no
// need to exact struct again
});

return structMap.values().stream()
Expand Down Expand Up @@ -711,7 +743,12 @@ private String addParameters(
typeName = structClassNameMap.get(namedTypes.get(i).structIdentifier());
} else if (namedTypes.get(i).getType().startsWith("tuple")
&& namedTypes.get(i).getType().contains("[")) {
typeName = buildStructArrayTypeName(namedTypes.get(i));
TypeName argument =
((ParameterizedTypeName) buildStructArrayTypeName(namedTypes.get(i)))
.typeArguments.get(0);
typeName =
ParameterizedTypeName.get(
ClassName.get(List.class), ClassName.get("", argument.toString()));
} else {
typeName = getNativeType(inputParameterTypes.get(i).type);
}
Expand Down Expand Up @@ -992,7 +1029,6 @@ private MethodSpec buildFunction(ABIDefinition functionDefinition)
} else {
this.buildTransactionFunction(functionDefinition, methodBuilder, inputParams);
}

return methodBuilder.build();
}

Expand Down Expand Up @@ -1184,7 +1220,12 @@ private void buildConstantFunction(
nativeReturnTypeName = structClassNameMap.get(outputType.structIdentifier());
} else if (outputType.getType().startsWith("tuple")
&& outputType.getType().contains("[")) {
nativeReturnTypeName = buildStructArrayTypeName(outputType);
TypeName argument =
((ParameterizedTypeName) buildStructArrayTypeName(outputType))
.typeArguments.get(0);
nativeReturnTypeName =
ParameterizedTypeName.get(
ClassName.get(List.class), ClassName.get("", argument.toString()));
} else {
nativeReturnTypeName = this.getWrapperRawType(typeName);
}
Expand Down Expand Up @@ -1221,6 +1262,10 @@ private void buildConstantFunction(
callCode.addStatement("return convertToNative(result)");
methodBuilder.returns(nativeReturnTypeName).addCode(callCode.build());
} else {
if (outputType.getType().startsWith("tuple")
&& outputType.getType().contains("[")) {
nativeReturnTypeName = ClassName.get(List.class);
}
methodBuilder.addStatement(
"return executeCallWithSingleValueReturn(function, $T.class)",
nativeReturnTypeName);
Expand Down
121 changes: 121 additions & 0 deletions src/test/java/org/fisco/bcos/codegen/v3/test/CodeGenV3Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package org.fisco.bcos.codegen.v3.test;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import org.fisco.bcos.codegen.CodeGenMain;
import org.junit.Assert;
import org.junit.Test;

public class CodeGenV3Test {
private static final String JAVA_OUTPUT_DIR = "sdk";
private static final String DEFAULT_PACKAGE = "com";

static class MyJavaFileObject extends SimpleJavaFileObject {

private String source;
private ByteArrayOutputStream outputStream;

/**
* Construct a SimpleJavaFileObject of the given kind and with the given URI.
*
* @param uri the URI for this file object
* @param kind the kind of this file object
*/
protected MyJavaFileObject(URI uri, Kind kind) {
super(uri, kind);
}

public MyJavaFileObject(String name, String source) {
this(URI.create("String:///" + name + Kind.SOURCE.extension), Kind.SOURCE);
this.source = source;
}

@Override
public OutputStream openOutputStream() throws IOException {
outputStream = new ByteArrayOutputStream();
return outputStream;
}

@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
if (source == null) {
throw new IOException("Empty source");
}
return source;
}
}

@Test
public void complexABICodeGen() throws IOException {
final String COMPLEX_ABI_FILE = "ComplexCodecTest.abi";
final String COMPLEX_NAME = "ComplexCodecTest";
codeGenTest(COMPLEX_ABI_FILE, COMPLEX_NAME);
}

@Test
public void tableABICodeGen() throws IOException {
final String ABI_FILE = "Table.abi";
final String CONTRACT_NAME = "Table";
codeGenTest(ABI_FILE, CONTRACT_NAME);
}

private void codeGenTest(String abiFileName, String contractName) throws IOException {
String abiFile = CodeGenV3Test.class.getClassLoader().getResource(abiFileName).getPath();
String javaOutPut = new File(abiFile).getParent() + File.separator + JAVA_OUTPUT_DIR;
CodeGenMain.main(
Arrays.asList(
"-v", "V3",
"-a", abiFile,
"-b", abiFile,
"-s", abiFile,
"-p", DEFAULT_PACKAGE,
"-o", javaOutPut)
.toArray(new String[0]));
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> collector = new DiagnosticCollector<>();
JavaFileManager javaFileManager =
compiler.getStandardFileManager(collector, null, StandardCharsets.UTF_8);
String codeFileName =
javaOutPut
+ File.separator
+ File.separator
+ DEFAULT_PACKAGE
+ File.separator
+ contractName
+ ".java";

File codeFile = new File(codeFileName);
Long fileLength = codeFile.length();
byte[] fileContent = new byte[fileLength.intValue()];
FileInputStream in = new FileInputStream(codeFile);
in.read(fileContent);
in.close();
String code = new String(fileContent, StandardCharsets.UTF_8);

JavaFileObject myJavaFileObject = new MyJavaFileObject(contractName, code);
Boolean call =
compiler.getTask(
null,
javaFileManager,
collector,
null,
null,
Collections.singletonList(myJavaFileObject))
.call();
collector.getDiagnostics().forEach(log -> System.out.println(log.toString()));
Assert.assertTrue(call);
}
}
1 change: 1 addition & 0 deletions src/test/resources/ComplexCodecTest.abi
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"conflictFields":[{"kind":3,"slot":1,"value":[0]},{"kind":3,"slot":1,"value":[1]},{"kind":4,"value":[1]}],"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"b32_array_array","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"selector":[361941394,1422834829],"stateMutability":"view","type":"function"},{"conflictFields":[{"kind":3,"slot":3,"value":[0]},{"kind":4,"value":[3]}],"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"b32_s_array_array","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"selector":[1849978875,3517985529],"stateMutability":"view","type":"function"},{"conflictFields":[{"kind":0},{"kind":3,"slot":0,"value":[0]},{"kind":3,"slot":0,"value":[1]},{"kind":4,"value":[0]}],"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"b_array_array","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"selector":[1350133985,3395322268],"stateMutability":"view","type":"function"},{"conflictFields":[{"kind":0},{"kind":3,"slot":2,"value":[0]},{"kind":4,"value":[2]}],"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"b_s_array_array","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"selector":[2512437014,1940483310],"stateMutability":"view","type":"function"},{"conflictFields":[{"kind":5}],"inputs":[{"components":[{"internalType":"int128","name":"i1","type":"int128"},{"internalType":"uint128","name":"u1","type":"uint128"},{"internalType":"int32[1]","name":"b1","type":"int32[1]"}],"internalType":"struct StaticStruct","name":"b","type":"tuple"}],"name":"buildStaticStruct","outputs":[{"components":[{"internalType":"int128","name":"i1","type":"int128"},{"internalType":"uint128","name":"u1","type":"uint128"},{"internalType":"int32[1]","name":"b1","type":"int32[1]"}],"internalType":"struct StaticStruct","name":"","type":"tuple"}],"selector":[1732779260,1182195354],"stateMutability":"pure","type":"function"},{"conflictFields":[{"kind":5}],"inputs":[{"internalType":"int128","name":"i1","type":"int128"},{"internalType":"uint128","name":"u1","type":"uint128"}],"name":"buildStaticStruct","outputs":[{"components":[{"internalType":"int128","name":"i1","type":"int128"},{"internalType":"uint128","name":"u1","type":"uint128"},{"internalType":"int32[1]","name":"b1","type":"int32[1]"}],"internalType":"struct StaticStruct","name":"","type":"tuple"}],"selector":[2268489121,274923318],"stateMutability":"pure","type":"function"},{"conflictFields":[{"kind":0},{"kind":4,"value":[4]},{"kind":4,"value":[5]}],"inputs":[{"internalType":"string","name":"value_str","type":"string"},{"internalType":"bytes32[]","name":"_b","type":"bytes32[]"}],"name":"buildStructA","outputs":[{"components":[{"internalType":"string[]","name":"value_str","type":"string[]"},{"internalType":"bytes32[]","name":"bytes32_in_struct","type":"bytes32[]"}],"internalType":"struct StructA","name":"","type":"tuple"}],"selector":[451944255,2748848611],"stateMutability":"nonpayable","type":"function"},{"conflictFields":[{"kind":0},{"kind":4,"value":[4]},{"kind":4,"value":[5]}],"inputs":[{"components":[{"internalType":"string[]","name":"value_str","type":"string[]"},{"internalType":"bytes32[]","name":"bytes32_in_struct","type":"bytes32[]"}],"internalType":"struct StructA","name":"a","type":"tuple"}],"name":"buildStructB","outputs":[{"components":[{"internalType":"string[]","name":"d_str","type":"string[]"},{"components":[{"internalType":"string[]","name":"value_str","type":"string[]"},{"internalType":"bytes32[]","name":"bytes32_in_struct","type":"bytes32[]"}],"internalType":"struct StructA[]","name":"a_struct","type":"tuple[]"}],"internalType":"struct StructB","name":"","type":"tuple"}],"selector":[2715886304,3473861522],"stateMutability":"nonpayable","type":"function"},{"conflictFields":[{"kind":0},{"kind":4,"value":[4]},{"kind":4,"value":[5]}],"inputs":[{"components":[{"internalType":"string[]","name":"d_str","type":"string[]"},{"components":[{"internalType":"string[]","name":"value_str","type":"string[]"},{"internalType":"bytes32[]","name":"bytes32_in_struct","type":"bytes32[]"}],"internalType":"struct StructA[]","name":"a_struct","type":"tuple[]"}],"internalType":"struct StructB","name":"b","type":"tuple"}],"name":"getStructAInStructB","outputs":[{"components":[{"internalType":"string[]","name":"value_str","type":"string[]"},{"internalType":"bytes32[]","name":"bytes32_in_struct","type":"bytes32[]"}],"internalType":"struct StructA","name":"","type":"tuple"}],"selector":[3302412820,2294370420],"stateMutability":"nonpayable","type":"function"},{"conflictFields":[{"kind":0},{"kind":4,"value":[1]}],"inputs":[{"internalType":"bytes32[][]","name":"b","type":"bytes32[][]"}],"name":"setBytes32ArrayArray","outputs":[{"internalType":"bytes32[][]","name":"","type":"bytes32[][]"}],"selector":[2425465556,973599251],"stateMutability":"nonpayable","type":"function"},{"conflictFields":[{"kind":0},{"kind":4,"value":[3]}],"inputs":[{"internalType":"bytes32[10][]","name":"b","type":"bytes32[10][]"}],"name":"setBytes32StaticArrayArray","outputs":[{"internalType":"bytes32[10][]","name":"","type":"bytes32[10][]"}],"selector":[3554602330,3667350222],"stateMutability":"nonpayable","type":"function"},{"conflictFields":[{"kind":0},{"kind":4,"value":[0]}],"inputs":[{"internalType":"bytes[][]","name":"b","type":"bytes[][]"}],"name":"setBytesArrayArray","outputs":[{"internalType":"bytes[][]","name":"","type":"bytes[][]"}],"selector":[68407213,3571060108],"stateMutability":"nonpayable","type":"function"},{"conflictFields":[{"kind":0},{"kind":4,"value":[2]}],"inputs":[{"internalType":"bytes[10][]","name":"b","type":"bytes[10][]"}],"name":"setBytesStaticArrayArray","outputs":[{"internalType":"bytes[10][]","name":"","type":"bytes[10][]"}],"selector":[2318966447,544764711],"stateMutability":"nonpayable","type":"function"}]
Loading

0 comments on commit 5232778

Please sign in to comment.