Skip to content

Commit

Permalink
<feat>(command): merge all dependencies sol file to one sol file. (#853)
Browse files Browse the repository at this point in the history
  • Loading branch information
kyonRay authored Aug 14, 2024
1 parent f6cdd1d commit 0d4a29f
Showing 1 changed file with 109 additions and 59 deletions.
168 changes: 109 additions & 59 deletions src/main/java/console/contract/utils/ContractCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,13 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Scanner;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
import org.fisco.bcos.codegen.v3.exceptions.CodeGenException;
import org.fisco.bcos.codegen.v3.utils.CodeGenUtils;
Expand Down Expand Up @@ -70,27 +75,25 @@ public static AbiAndBin compileContract(
throws CompileContractException {
// if absolute path
File contractFile = new File(contractNameOrPath);
// the contractPath
if (contractFile.exists() && !contractFile.isDirectory()) {
return dynamicCompileSolFilesToJava(
contractFile, specifyContractName, sm, isContractParallelAnalysis, version);
}

// if absolute path without sol
// try again with .sol suffix
contractFile = new File(contractNameOrPath + SOL_SUFFIX);
if (contractFile.exists() && !contractFile.isDirectory()) {
return dynamicCompileSolFilesToJava(
contractFile, specifyContractName, sm, isContractParallelAnalysis, version);
}

// if relative path in contracts/
// the contractName
String contractFileName = ConsoleUtils.removeSolSuffix(contractNameOrPath) + SOL_SUFFIX;
contractFile = new File(SOLIDITY_PATH + File.separator + contractFileName);
if (!contractFile.exists()) {
throw new CompileContractException(
"There is no " + contractFileName + " in the directory of " + SOLIDITY_PATH);
if (!contractFile.exists() || contractFile.isDirectory()) {
// if absolute path without sol
// try again with .sol suffix
contractFile = new File(contractNameOrPath + SOL_SUFFIX);
if (!contractFile.exists() || contractFile.isDirectory()) {
// if relative path in contracts/
// the contractName
String contractFileName =
ConsoleUtils.removeSolSuffix(contractNameOrPath) + SOL_SUFFIX;
contractFile = new File(SOLIDITY_PATH + File.separator + contractFileName);
if (!contractFile.exists()) {
throw new CompileContractException(
"There is no "
+ contractFileName
+ " in the directory of "
+ SOLIDITY_PATH);
}
}
}
return dynamicCompileSolFilesToJava(
contractFile, specifyContractName, sm, isContractParallelAnalysis, version);
Expand Down Expand Up @@ -131,53 +134,42 @@ public static AbiAndBin compileSolToBinAndAbi(
boolean isContractParallelAnalysis,
Version version)
throws IOException, CompileContractException {
if (compileType == OnlyNonSM) {
return compileSolToBinAndAbi(
contractFile,
abiDir,
binDir,
false,
librariesOption,
specifyContractName,
isContractParallelAnalysis,
version);
} else if (compileType == OnlySM) {
if (compileType != All) {
return compileSolToBinAndAbi(
contractFile,
abiDir,
binDir,
true,
compileType == OnlySM,
librariesOption,
specifyContractName,
isContractParallelAnalysis,
version);
} else {
AbiAndBin abiAndBin =
compileSolToBinAndAbi(
contractFile,
abiDir,
binDir,
false,
librariesOption,
specifyContractName,
isContractParallelAnalysis,
version);
AbiAndBin abiAndBinSM =
compileSolToBinAndAbi(
contractFile,
abiDir,
binDir,
true,
librariesOption,
specifyContractName,
isContractParallelAnalysis,
version);
return new AbiAndBin(
abiAndBin.getAbi(),
abiAndBin.getBin(),
abiAndBinSM.getSmBin(),
abiAndBin.getDevdoc());
}
AbiAndBin abiAndBin =
compileSolToBinAndAbi(
contractFile,
abiDir,
binDir,
false,
librariesOption,
specifyContractName,
isContractParallelAnalysis,
version);
AbiAndBin abiAndBinSM =
compileSolToBinAndAbi(
contractFile,
abiDir,
binDir,
true,
librariesOption,
specifyContractName,
isContractParallelAnalysis,
version);
return new AbiAndBin(
abiAndBin.getAbi(),
abiAndBin.getBin(),
abiAndBinSM.getSmBin(),
abiAndBin.getDevdoc());
}

// compile with libraries option
Expand Down Expand Up @@ -220,9 +212,15 @@ public static AbiAndBin compileSolToBinAndAbi(
} else {
logger.debug("compileSolToBinAndAbi, solc version:{}", version);
}

String fileName = contractFile.getName();
String dir = contractFile.getParentFile().getCanonicalPath() + File.separator;

String mergedSource = mergeSource(dir, fileName, new HashSet<>());

SolidityCompiler.Result res =
SolidityCompiler.compile(
contractFile,
mergedSource.getBytes(StandardCharsets.UTF_8),
sm,
true,
version,
Expand Down Expand Up @@ -276,6 +274,58 @@ public static AbiAndBin compileSolToBinAndAbi(
return abiAndBin;
}

public static String mergeSource(String currentDir, String sourceFile, Set<String> dependencies)
throws IOException {
StringBuilder sourceBuffer = new StringBuilder();

String fullPath = currentDir + sourceFile;
String dir = fullPath.substring(0, fullPath.lastIndexOf(File.separator)) + File.separator;

File sourceResource = new File(fullPath);

if (!sourceResource.exists()) {
throw new IOException("Source file:" + fullPath + " not found");
}

Pattern pattern = Pattern.compile("^\\s*import\\s+[\"'](.+)[\"']\\s*;\\s*$");
try (Scanner scanner = new Scanner(sourceResource, "UTF-8")) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.contains("pragma experimental ABIEncoderV2;")) {
if (!dependencies.contains("pragma experimental ABIEncoderV2;")) {
dependencies.add("pragma experimental ABIEncoderV2;");
sourceBuffer.append(line);
sourceBuffer.append(System.lineSeparator());
}
continue;
}

// skip SPDX-License-Identifier
if (line.contains("SPDX-License-Identifier")) {
continue;
}

Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
String depSourcePath = matcher.group(1);
String nextPath = dir + depSourcePath;
if (nextPath.contains("./")) {
nextPath = new File(nextPath).getCanonicalPath();
}
if (!dependencies.contains(nextPath)) {
dependencies.add(nextPath);
sourceBuffer.append(mergeSource(dir, depSourcePath, dependencies));
}
} else {
sourceBuffer.append(line);
sourceBuffer.append(System.lineSeparator());
}
}
}

return sourceBuffer.toString();
}

public static void checkBinaryCode(String contractName, String binary)
throws CompileContractException {
String externalLibSplitter = "_";
Expand Down

0 comments on commit 0d4a29f

Please sign in to comment.