Skip to content

Commit

Permalink
feat(extensions): add options parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
emretepedev committed Jan 24, 2023
1 parent ed3b6ed commit 5519876
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 56 deletions.
113 changes: 73 additions & 40 deletions src/extensions/Finder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,24 @@ import type {
HardhatRuntimeEnvironment,
} from "hardhat/types";
import { normalize } from "path";
import {
defaultExtensionCompilerTaskArgs,
defaultExtensionOptions,
} from "~/config";
import { PLUGIN_NAME } from "~/constants";
import type {
CompilerOutputBytecode,
CompilerOutputContract,
CompilerTaskArguments,
CompilerTaskUserArguments,
ContractInfo,
FinderExtensionArguments,
FinderExtensionOptions,
Metadata,
SolcConfig,
SourceDependencies,
} from "~/types";
import { useWarningConsole } from "~/utils";
import { merge, useErrorMessage, useWarningConsole } from "~/utils";

// TODO: add setByAddress (hardhat --network foo finder ...)
// TODO: add asm, function-debug, function-debug-runtime, flatten source
Expand All @@ -36,47 +43,54 @@ export class Finder {
this.hre = hre;
}

public setFor = async (
contractPath?: string,
contractName?: string,
noCompile: boolean = this.hre.config.finder.noCompile,
compilerTaskArgs: Partial<CompilerTaskArguments> = {}
) => {
contractPath ||= this.hre.config.finder?.contract?.path;
contractName ||= this.hre.config.finder?.contract?.name;
public setFor = async ({
contractPath,
contractName,
compilerTaskArgs,
options,
}: FinderExtensionArguments = {}) => {
contractPath ??= this.hre.userConfig?.finder?.contract?.path;
contractName ??= this.hre.userConfig?.finder?.contract?.name;

if (!contractPath || !contractName) {
throw new HardhatPluginError(
PLUGIN_NAME,
"Contract path or name is not found!\n" +
"Make sure the Finder.setFor() arguments are correctly provided, or 'config.finder.contract' is set."
useErrorMessage(
"Contract path or name not found!\n" +
"Make sure the Finder.setFor() arguments are correctly provided, or 'finder.contract' is set in your Hardhat config."
)
);
}

this._setInitialContractInfo(contractPath, contractName);
const { noCompile, hideWarnings } = merge<FinderExtensionOptions>(
defaultExtensionOptions,
options
);

compilerTaskArgs = merge<CompilerTaskArguments>(
defaultExtensionCompilerTaskArgs,
compilerTaskArgs,
{ noFinder: defaultExtensionCompilerTaskArgs.noFinder }
);

if (!noCompile && !this.compiledOnce) {
this.compiledOnce = true;

for (const compiler of this.hre.config.solidity.compilers) {
(compiler.settings as SolcConfig).outputSelection["*"]["*"].push(
"storageLayout"
);
}

compilerTaskArgs.noFinder = true;
await this.hre.run(TASK_COMPILE, compilerTaskArgs);
await this.compile(compilerTaskArgs);
} else {
if (!this.compiledOnce && !this.warnedOnce) {
this.warnedOnce = true;

useWarningConsole(
"These arguments or functions do NOT work as expected when 'noCompile' option is true:\n" +
"- storage-layout / getStorageLayout()"
);
if (!hideWarnings) {
useWarningConsole(
"These arguments or functions do NOT work as expected when 'noCompile' option is true:\n" +
"- storage-layout / getStorageLayout()"
);
}
}
}

this.setInitialContractInfo(contractPath, contractName);
this.contractArtifact = this.getArtifact();
this.contractBuildInfo = await this.getBuildInfo();
this.contractOutput =
Expand All @@ -96,10 +110,12 @@ export class Finder {
} catch (error: any) {
throw new HardhatPluginError(
PLUGIN_NAME,
"\nThere is no Artifact for target contract.\n" +
"Make sure the contract path and name are valid.\n" +
"Make sure the artifacts exist.\n" +
"Compile with hardhat or re-run this task without --no-compile flag to create new artifacts.",
useErrorMessage(
"There is no Artifact for target contract.\n" +
"Make sure the contract path and name are valid.\n" +
"Make sure the artifacts exist.\n" +
"Compile with hardhat or re-run this task without --no-compile flag to create new artifacts."
),
error as Error
);
}
Expand All @@ -113,10 +129,12 @@ export class Finder {
if (!buildInfo) {
throw new HardhatPluginError(
PLUGIN_NAME,
"\nThere is no Build Info for target contract.\n" +
"Make sure the contract path and name are valid.\n" +
"Make sure the artifacts exist.\n" +
"Compile with hardhat or re-run this task without --no-compile flag to create new artifacts."
useErrorMessage(
"There is no Build Info for target contract.\n" +
"Make sure the contract path and name are valid.\n" +
"Make sure the artifacts exist.\n" +
"Compile with hardhat or re-run this task without --no-compile flag to create new artifacts."
)
);
}

Expand All @@ -138,7 +156,7 @@ export class Finder {
} catch (error: any) {
throw new HardhatPluginError(
PLUGIN_NAME,
"\nInvalid metadata file",
useErrorMessage("Invalid metadata file."),
error as Error
);
}
Expand Down Expand Up @@ -314,39 +332,54 @@ export class Finder {
return sourceMapRuntime;
};

private _setInitialContractInfo = (
private setInitialContractInfo = (
contractPath: string,
contractName: string
) => {
const userRootPath = this.hre.userConfig?.paths?.root
? `${normalize(this.hre.userConfig.paths.root)}/`
: "";

this._validate(
this.validate(
(this.contractPath = normalize(contractPath).replace(userRootPath, "")),
(this.contractName = contractName)
);

this.contractFullyQualifiedName = this.getFullyQualifiedName();
};

private _validate = (contractPath: string, contractName: string) => {
private validate = (contractPath: string, contractName: string) => {
const contractPathRegexp = new RegExp("\\.sol$");
if (!contractPathRegexp.test(contractPath)) {
throw new HardhatPluginError(
PLUGIN_NAME,
`\nInvalid Path File: '${contractPath}'.\n` +
"Make sure the contract path points to a '.sol' file.\n" +
"Example: contracts/Foo.sol"
useErrorMessage(
`Invalid Path File: '${contractPath}'.\n` +
"Make sure the contract path points to a '.sol' file.\n" +
"Example: contracts/Foo.sol"
)
);
}

const contractNameRegexp = new RegExp("^[\\w\\d$]+$", "i");
if (!contractNameRegexp.test(contractName)) {
throw new HardhatPluginError(
PLUGIN_NAME,
`\nInvalid contract name: '${contractName}'.`
useErrorMessage(`Invalid contract name: '${contractName}'.`)
);
}
};

private compile = async (taskArgs: CompilerTaskUserArguments) => {
for (const compiler of this.hre.config.solidity.compilers) {
// TODO: check for more outputs https://docs.soliditylang.org/en/v0.8.17/using-the-compiler.html
// To select all outputs the compiler can possibly generate, use
// "outputSelection: { "*": { "*": [ "*" ], "": [ "*" ] } }"
(compiler.settings as SolcConfig).outputSelection["*"]["*"].push(
"storageLayout"
);
}

await this.hre.run(TASK_COMPILE, taskArgs);
};
}
11 changes: 6 additions & 5 deletions src/tasks/compile.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { TASK_COMPILE } from "hardhat/builtin-tasks/task-names";
import { task } from "hardhat/config";
import type { ActionType, TaskArguments } from "hardhat/types";
import type { ActionType } from "hardhat/types";
import { TASK_FINDER } from "~/constants";
import type { CompilerTaskArguments, FinderTaskArguments } from "~/types";
import type { CompilerTaskUserArguments, FinderTaskArguments } from "~/types";

const compileAction: ActionType<TaskArguments> = async (
taskArgs: CompilerTaskArguments,
const compileAction: ActionType<CompilerTaskUserArguments> = async (
taskArgs,
{ run, config },
runSuper
) => {
Expand All @@ -20,11 +20,12 @@ const compileAction: ActionType<TaskArguments> = async (
: config.finder.maxStringLength,
noCompile: true,
};

await run(TASK_FINDER, finderTaskArguments);
}
};

task<CompilerTaskArguments>(TASK_COMPILE)
task<CompilerTaskUserArguments>(TASK_COMPILE)
.addFlag(
"noFinder",
"Don't run Finder after running this task, even if finder.runOnCompile option is true"
Expand Down
38 changes: 27 additions & 11 deletions src/tasks/finder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import type { ActionType } from "hardhat/types";
import type { InspectOptions } from "util";
import { PLUGIN_NAME, SUPPORTED_OUTPUTS, TASK_FINDER } from "~/constants";
import type { ContractInfo, FinderTaskArguments } from "~/types";
import { formatOutputName, useInspectConsole } from "~/utils";
import {
formatOutputName,
useErrorMessage,
useHeaderConsole,
useInspectConsole,
useSubheaderConsole,
} from "~/utils";

const finderAction: ActionType<FinderTaskArguments> = async (
{
Expand Down Expand Up @@ -36,7 +42,14 @@ const finderAction: ActionType<FinderTaskArguments> = async (

validateTaskArguments();

await finder.setFor(path, name, noCompile);
await finder.setFor({
contractPath: path,
contractName: name,
options: {
noCompile,
},
});

const fullyQualifiedName = finder.getFullyQualifiedName();
const contractsInfo: ContractInfo[] = [
{
Expand All @@ -63,11 +76,12 @@ const finderAction: ActionType<FinderTaskArguments> = async (
};

for (const contractInfo of contractsInfo) {
console.log(`@@@@@@@ ${contractInfo.fullyQualifiedName} @@@@@@@`);
if (
contractInfo.fullyQualifiedName !== contractsInfo[0].fullyQualifiedName
) {
await finder.setFor(contractInfo.path, contractInfo.name, noCompile);
useHeaderConsole(`@@@@@@@ ${contractInfo.fullyQualifiedName} @@@@@@@`);
if (contractInfo.fullyQualifiedName !== fullyQualifiedName) {
await finder.setFor({
contractPath: contractInfo.path,
contractName: contractInfo.name,
});
}

for (const output of outputs) {
Expand All @@ -77,8 +91,8 @@ const finderAction: ActionType<FinderTaskArguments> = async (
const result = (await (finder as any)[functionName]()) as unknown;
const content = prettify ? result : JSON.stringify(result);

console.log(
`======= ${outputName.humanReadableFormat} ======= (${finder.contractFullyQualifiedName})`
useSubheaderConsole(
`======= ${outputName.humanReadableFormat} ======= (${contractInfo.fullyQualifiedName})`
);
useInspectConsole(content, inspectOptions);
}
Expand Down Expand Up @@ -109,8 +123,10 @@ const finderAction: ActionType<FinderTaskArguments> = async (
if (!SUPPORTED_OUTPUTS.includes(output)) {
throw new HardhatPluginError(
PLUGIN_NAME,
`\nUnsupported Output: '${output}'.\n` +
`All supported contract outputs: ${SUPPORTED_OUTPUTS.toString()}`
useErrorMessage(
`Unsupported Output: '${output}'.\n` +
`All supported contract outputs: ${SUPPORTED_OUTPUTS.toString()}`
)
);
}
});
Expand Down

0 comments on commit 5519876

Please sign in to comment.