mirror of
https://github.com/cerc-io/watcher-ts
synced 2025-01-06 19:38:05 +00:00
Add flag in codegen to ignore errors for unhandled types (#350)
* Add --continue-on-error flag to codegen for skipping unhandled data types * Use solc version defined in config * Fix codegen log for unhandled array types * Log solc compilation errors --------- Co-authored-by: Dhruv Srivastava <dhruvdhs.ds@gmail.com>
This commit is contained in:
parent
8c928516f8
commit
754db311f0
@ -4,13 +4,17 @@
|
||||
|
||||
import solc from 'solc';
|
||||
|
||||
interface Solc {
|
||||
compile(input: string): any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the given contract using solc and returns resultant artifacts.
|
||||
* @param contractContent Contents of the contract file to be compiled.
|
||||
* @param contractFileName Input contract file name.
|
||||
* @param contractName Name of the main contract in the contract file.
|
||||
*/
|
||||
export function generateArtifacts (contractContent: string, contractFileName: string, contractName: string): { abi: any[], storageLayout: any } {
|
||||
export async function generateArtifacts (contractContent: string, contractFileName: string, contractName: string, solcVersion: string): Promise<{ abi: any[], storageLayout: any }> {
|
||||
const input: any = {
|
||||
language: 'Solidity',
|
||||
sources: {},
|
||||
@ -27,6 +31,31 @@ export function generateArtifacts (contractContent: string, contractFileName: st
|
||||
content: contractContent
|
||||
};
|
||||
|
||||
const solcInstance = (solcVersion === undefined) ? solc : await getSolcByVersion(solcVersion);
|
||||
const compiledContract = JSON.parse(solcInstance.compile(JSON.stringify(input)));
|
||||
|
||||
if (compiledContract.errors?.length) {
|
||||
compiledContract.errors.forEach((error: any) => {
|
||||
if (error.severity === 'error') {
|
||||
throw new Error(error.formattedMessage);
|
||||
}
|
||||
|
||||
console.log(`${error.severity}: ${error.formattedMessage}`);
|
||||
});
|
||||
}
|
||||
|
||||
// Get artifacts for the required contract.
|
||||
return JSON.parse(solc.compile(JSON.stringify(input))).contracts[contractFileName][contractName];
|
||||
return compiledContract.contracts[contractFileName][contractName];
|
||||
}
|
||||
|
||||
async function getSolcByVersion (solcVersion: string): Promise<Solc> {
|
||||
return new Promise((resolve, reject) => {
|
||||
solc.loadRemoteVersion(solcVersion, (err: any, solcInstance: Solc | Promise<any>) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(solcInstance);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -47,6 +47,13 @@ const main = async (): Promise<void> => {
|
||||
describe: 'Watcher generation config file path (yaml)',
|
||||
type: 'string'
|
||||
})
|
||||
.option('continue-on-error', {
|
||||
alias: 'e',
|
||||
demandOption: false,
|
||||
default: false,
|
||||
describe: 'Continue generating watcher if unhandled types encountered',
|
||||
type: 'boolean'
|
||||
})
|
||||
.argv;
|
||||
|
||||
const config = getConfig(path.resolve(argv['config-file']));
|
||||
@ -83,10 +90,11 @@ const main = async (): Promise<void> => {
|
||||
// Generate artifacts from contract.
|
||||
const inputFileName = path.basename(inputFile, '.sol');
|
||||
|
||||
const { abi, storageLayout } = generateArtifacts(
|
||||
const { abi, storageLayout } = await generateArtifacts(
|
||||
contractData.contractString,
|
||||
`${inputFileName}.sol`,
|
||||
contractData.contractName
|
||||
contractData.contractName,
|
||||
config.solc
|
||||
);
|
||||
|
||||
contractData.contractAbi = abi;
|
||||
@ -96,7 +104,8 @@ const main = async (): Promise<void> => {
|
||||
contracts.push(contractData);
|
||||
}
|
||||
|
||||
const visitor = new Visitor();
|
||||
const continueOnError = argv['continue-on-error'];
|
||||
const visitor = new Visitor(continueOnError);
|
||||
|
||||
parseAndVisit(visitor, contracts, config.mode);
|
||||
|
||||
@ -379,6 +388,7 @@ function getConfig (configFile: string): any {
|
||||
mode: inputConfig.mode || MODE_ALL,
|
||||
kind: inputConfig.kind || KIND_ACTIVE,
|
||||
port: inputConfig.port || DEFAULT_PORT,
|
||||
solc: inputConfig.solc,
|
||||
flatten,
|
||||
subgraphPath,
|
||||
subgraphConfig
|
||||
|
@ -25,10 +25,11 @@ export class Visitor {
|
||||
_database: Database;
|
||||
_client: Client;
|
||||
_types: Types;
|
||||
_continueOnError: boolean;
|
||||
|
||||
_contract?: { name: string, kind: string };
|
||||
|
||||
constructor () {
|
||||
constructor (continueOnErrorFlag = false) {
|
||||
this._schema = new Schema();
|
||||
this._resolvers = new Resolvers();
|
||||
this._indexer = new Indexer();
|
||||
@ -36,6 +37,7 @@ export class Visitor {
|
||||
this._database = new Database();
|
||||
this._client = new Client();
|
||||
this._types = new Types();
|
||||
this._continueOnError = continueOnErrorFlag;
|
||||
}
|
||||
|
||||
setContract (name: string, kind: string): void {
|
||||
@ -56,25 +58,44 @@ export class Visitor {
|
||||
return { name: item.name, type: item.typeName.name };
|
||||
});
|
||||
|
||||
const typeName = node.returnParameters[0].typeName;
|
||||
let errorMessage = '';
|
||||
|
||||
// TODO Handle user defined type return.
|
||||
if (typeName.type === 'UserDefinedTypeName') {
|
||||
// Skip in case of UserDefinedTypeName.
|
||||
return;
|
||||
const typeName = node.returnParameters[0].typeName;
|
||||
switch (typeName.type) {
|
||||
case 'ElementaryTypeName': {
|
||||
const returnType = typeName.name;
|
||||
|
||||
this._schema.addQuery(name, params, returnType);
|
||||
this._resolvers.addQuery(name, params, returnType);
|
||||
this._entity.addQuery(name, params, returnType);
|
||||
this._database.addQuery(name, params, returnType);
|
||||
this._client.addQuery(name, params, returnType);
|
||||
|
||||
assert(this._contract);
|
||||
this._indexer.addQuery(this._contract.name, MODE_ETH_CALL, name, params, returnType);
|
||||
|
||||
break;
|
||||
}
|
||||
case 'UserDefinedTypeName':
|
||||
errorMessage = `No support in codegen for user defined return type from method "${node.name}"`;
|
||||
break;
|
||||
|
||||
case 'ArrayTypeName':
|
||||
errorMessage = `No support in codegen for return type "${typeName.baseTypeName.name}[]" from method "${node.name}"`;
|
||||
break;
|
||||
|
||||
default:
|
||||
errorMessage = `No support in codegen for return type "${typeName.type}" from method "${node.name}"`;
|
||||
}
|
||||
|
||||
// TODO Handle multiple return parameters and array return type.
|
||||
const returnType = typeName.name;
|
||||
if (errorMessage !== '') {
|
||||
if (this._continueOnError) {
|
||||
console.log(errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
this._schema.addQuery(name, params, returnType);
|
||||
this._resolvers.addQuery(name, params, returnType);
|
||||
this._entity.addQuery(name, params, returnType);
|
||||
this._database.addQuery(name, params, returnType);
|
||||
this._client.addQuery(name, params, returnType);
|
||||
|
||||
assert(this._contract);
|
||||
this._indexer.addQuery(this._contract.name, MODE_ETH_CALL, name, params, returnType);
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user