Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<feat>(command): merge all dependencies sol file to one sol file. #853

Merged
merged 1 commit into from
Aug 14, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading