Skip to content

Commit

Permalink
Apply exlucde filter to imported paths
Browse files Browse the repository at this point in the history
  • Loading branch information
Amxx committed Mar 19, 2024
1 parent 3e41699 commit 9e595d4
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 29 deletions.
24 changes: 19 additions & 5 deletions src/core.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@ test('snapshot', async t => {
const rootRelativeSourcesPath = path.relative(hre.config.paths.root, hre.config.paths.sources);
const sourcesPathPrefix = path.normalize(rootRelativeSourcesPath + '/');
const include = (sourceName: string) => sourceName.startsWith(sourcesPathPrefix);
const exclude = (sourceName: string) => false;

const [bip] = await hre.artifacts.getBuildInfoPaths();
const bi: BuildInfo = JSON.parse(await fs.readFile(bip!, 'utf8'));
const config = { paths: hre.config.paths, exposed: { ...baseConfig, initializers: false } };
const exposed = getExposed(bi.output, include, config);
const exposed = getExposed(bi.output, include, exclude, config);
const exposedFiles = [...exposed.values()].sort((a, b) => a.absolutePath.localeCompare(b.absolutePath))
for (const rf of exposedFiles) {
for (const rf of exposedFiles) {
t.snapshot(rf.content.rawContent);
}
});
Expand All @@ -30,7 +31,7 @@ test('snapshot initializers', async t => {
const [bip] = await hre.artifacts.getBuildInfoPaths();
const bi: BuildInfo = JSON.parse(await fs.readFile(bip!, 'utf8'));
const config = { paths: hre.config.paths, exposed: { ...baseConfig, initializers: true } };
const exposed = getExposed(bi.output, sourceName => sourceName === 'contracts/Initializers.sol', config);
const exposed = getExposed(bi.output, sourceName => sourceName === 'contracts/Initializers.sol', () => false, config);
const exposedFiles = [...exposed.values()].sort((a, b) => a.absolutePath.localeCompare(b.absolutePath))
for (const rf of exposedFiles) {
t.snapshot(rf.content.rawContent);
Expand All @@ -41,9 +42,22 @@ test('snapshot imports', async t => {
const [bip] = await hre.artifacts.getBuildInfoPaths();
const bi: BuildInfo = JSON.parse(await fs.readFile(bip!, 'utf8'));
const config = { paths: hre.config.paths, exposed: { ...baseConfig, initializers: false, imports: true } };
const exposed = getExposed(bi.output, sourceName => sourceName === 'contracts/Imported.sol', config);
const exposed = getExposed(bi.output, sourceName => sourceName === 'contracts/Imported.sol', () => false, config);
const exposedFiles = [...exposed.values()].sort((a, b) => a.absolutePath.localeCompare(b.absolutePath))
for (const rf of exposedFiles) {
for (const rf of exposedFiles) {
const absolutePath = path.relative(process.cwd(), rf.absolutePath);
const { rawContent } = rf.content;
t.snapshot({ absolutePath, rawContent });
}
});

test('snapshot exluded imports', async t => {
const [bip] = await hre.artifacts.getBuildInfoPaths();
const bi: BuildInfo = JSON.parse(await fs.readFile(bip!, 'utf8'));
const config = { paths: hre.config.paths, exposed: { ...baseConfig, initializers: false, imports: true } };
const exposed = getExposed(bi.output, sourceName => sourceName === 'contracts/Imported.sol', sourceName => sourceName =='contracts/Imported2.sol', config);
const exposedFiles = [...exposed.values()].sort((a, b) => a.absolutePath.localeCompare(b.absolutePath))
for (const rf of exposedFiles) {
const absolutePath = path.relative(process.cwd(), rf.absolutePath);
const { rawContent } = rf.content;
t.snapshot({ absolutePath, rawContent });
Expand Down
85 changes: 85 additions & 0 deletions src/core.test.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -1104,3 +1104,88 @@ Generated by [AVA](https://avajs.dev).
}␊
`,
}

## snapshot exluded imports

> Snapshot 1
{
absolutePath: 'contracts-exposed/$_/@openzeppelin/contracts/proxy/Clones.sol',
rawContent: `// SPDX-License-Identifier: UNLICENSED␊
pragma solidity >=0.6.0;␊
import "@openzeppelin/contracts/proxy/Clones.sol";␊
contract $Clones {␊
bytes32 public constant __hh_exposed_bytecode_marker = "hardhat-exposed";␊
event return$clone(address instance);␊
event return$cloneDeterministic(address instance);␊
constructor() payable {␊
}␊
function $clone(address implementation) external payable returns (address instance) {␊
(instance) = Clones.clone(implementation);␊
emit return$clone(instance);␊
}␊
function $cloneDeterministic(address implementation,bytes32 salt) external payable returns (address instance) {␊
(instance) = Clones.cloneDeterministic(implementation,salt);␊
emit return$cloneDeterministic(instance);␊
}␊
function $predictDeterministicAddress(address implementation,bytes32 salt,address deployer) external pure returns (address predicted) {␊
(predicted) = Clones.predictDeterministicAddress(implementation,salt,deployer);␊
}␊
function $predictDeterministicAddress(address implementation,bytes32 salt) external view returns (address predicted) {␊
(predicted) = Clones.predictDeterministicAddress(implementation,salt);␊
}␊
receive() external payable {}␊
}␊
`,
}

> Snapshot 2
{
absolutePath: 'contracts-exposed/Imported.sol',
rawContent: `// SPDX-License-Identifier: UNLICENSED␊
pragma solidity >=0.6.0;␊
import "../contracts/Imported.sol";␊
import "../contracts/Imported2.sol";␊
import "@openzeppelin/contracts/proxy/Clones.sol";␊
contract $NotImported is NotImported {␊
bytes32 public constant __hh_exposed_bytecode_marker = "hardhat-exposed";␊
constructor() payable {␊
}␊
receive() external payable {}␊
}␊
contract $Imported is Imported {␊
bytes32 public constant __hh_exposed_bytecode_marker = "hardhat-exposed";␊
constructor() payable {␊
}␊
function $_testNotImported(NotImported ni) external {␊
super._testNotImported(ni);␊
}␊
function $_testNotImported2(NotImported2 ni) external {␊
super._testNotImported2(ni);␊
}␊
receive() external payable {}␊
}␊
`,
}
Binary file modified src/core.test.ts.snap
Binary file not shown.
6 changes: 5 additions & 1 deletion src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const getExposedPath = (config: Config) => path.join(config.paths.root, c
export function getExposed(
solcOutput: SolcOutput,
include: (sourceName: string) => boolean,
exclude: (sourceName: string) => boolean,
config: Config,
): Map<string, ResolvedFile> {
const rootRelativeSourcesPath = path.relative(config.paths.root, config.paths.sources);
Expand All @@ -41,7 +42,7 @@ export function getExposed(
const imports: Record<string, Set<ContractDefinition>> = {};

for (const { ast } of Object.values(solcOutput.sources)) {
if (!include(ast.absolutePath)) {
if (!include(ast.absolutePath) || exclude(ast.absolutePath)) {
continue;
}

Expand Down Expand Up @@ -74,6 +75,9 @@ export function getExposed(
}

for (const [absoluteImportedPath, contracts] of Object.entries(imports)) {
if (exclude(absoluteImportedPath)) {
continue;
}
const filter: ContractFilter = node => contracts.has(node);
const ast = solcOutput.sources[absoluteImportedPath]?.ast;
assert(ast !== undefined);
Expand Down
29 changes: 6 additions & 23 deletions src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,15 @@ task<CompileJobArgs>(TASK_COMPILE_SOLIDITY_COMPILE_JOB, async (args, hre, superC
});

async function getExposedJob(hre: HardhatRuntimeEnvironment, compilationJob: CompilationJob, output: CompilerOutput): Promise<CompilationJob> {
const path = await import('path');
const { isMatch } = await import('micromatch');
const { getExposed } = await import('./core');

const inputFiles = Object.fromEntries(compilationJob.getResolvedFiles().map(rf => [rf.sourceName, rf.absolutePath]));
const sourcesDir = path.relative(hre.config.paths.root, hre.config.paths.sources);

const include = await getMatcher(hre.config);
const exposed = getExposed(output, include, hre.config);
const include = (sourceName: string) => sourceName.startsWith(sourcesDir) && hre.config.exposed.include.some(p => isMatch(path.relative(sourcesDir, sourceName), p));
const exclude = (sourceName: string) => hre.config.exposed.exclude.some(p => isMatch(path.relative(sourcesDir, sourceName), p));
const exposed = getExposed(output, include, exclude, hre.config);

const cj: CompilationJob = {
getResolvedFiles: () => [...exposed.values()],
Expand Down Expand Up @@ -121,23 +124,3 @@ async function cleanExposed(hre: HardhatRuntimeEnvironment) {
const exposedPath = getExposedPath(hre.config);
await fs.rm(exposedPath, { recursive: true, force: true });
}

async function getMatcher(config: HardhatConfig) {
const { isMatch } = await import('micromatch');
const path = await import('path');

const sourcesDir = path.relative(config.paths.root, config.paths.sources);
const includePatterns = config.exposed.include;
const excludePatterns = config.exposed.exclude;

return function (sourceName: string) {
if (!sourceName.startsWith(sourcesDir)) {
return false;
}
sourceName = path.relative(sourcesDir, sourceName);
return (
includePatterns.some(p => isMatch(sourceName, p)) &&
!excludePatterns.some(p => isMatch(sourceName, p))
);
};
}

0 comments on commit 9e595d4

Please sign in to comment.