From 686650c6a1ccb6aefcb8f91b1a2837bb2be85f27 Mon Sep 17 00:00:00 2001 From: Zou Guangxian Date: Tue, 14 Feb 2023 11:24:57 +0800 Subject: [PATCH] feat: support generating typings for specific contracts by patterns --- packages/hardhat/src/config.ts | 1 + packages/hardhat/src/index.ts | 8 ++- packages/hardhat/src/types.ts | 1 + packages/hardhat/test/project.test.ts | 80 +++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 2 deletions(-) diff --git a/packages/hardhat/src/config.ts b/packages/hardhat/src/config.ts index 23a3f7f19..fd4f03a6d 100644 --- a/packages/hardhat/src/config.ts +++ b/packages/hardhat/src/config.ts @@ -6,6 +6,7 @@ export function getDefaultTypechainConfig(config: HardhatConfig): TypechainConfi const defaultConfig: TypechainConfig = { outDir: 'typechain-types', target: 'ethers-v5', + artifacts: undefined, alwaysGenerateOverloads: false, discriminateTypes: false, tsNocheck: false, diff --git a/packages/hardhat/src/index.ts b/packages/hardhat/src/index.ts index 6c80e58dc..ccdf12929 100644 --- a/packages/hardhat/src/index.ts +++ b/packages/hardhat/src/index.ts @@ -66,8 +66,12 @@ subtask(TASK_TYPECHAIN_GENERATE_TYPES) } const cwd = config.paths.root + const artifactPatterns = typechainCfg.artifacts ?? [ + `${config.paths.artifacts}/!(build-info)/**/+([a-zA-Z0-9_]).json`, + ] + const { glob } = await import('typechain') - const allFiles = glob(cwd, [`${config.paths.artifacts}/!(build-info)/**/+([a-zA-Z0-9_]).json`]) + const allFiles = glob(cwd, artifactPatterns) if (typechainCfg.externalArtifacts) { allFiles.push(...glob(cwd, typechainCfg.externalArtifacts, false)) } @@ -88,7 +92,7 @@ subtask(TASK_TYPECHAIN_GENERATE_TYPES) const { runTypeChain } = await import('typechain') const result = await runTypeChain({ ...typechainOptions, - filesToProcess: needsFullRebuild ? allFiles : glob(cwd, artifactPaths), // only process changed files if not doing full rebuild + filesToProcess: needsFullRebuild ? allFiles : allFiles.filter((x: string) => artifactPaths.includes(x)), // only process changed files if not doing full rebuild }) if (!quiet) { diff --git a/packages/hardhat/src/types.ts b/packages/hardhat/src/types.ts index f16f47191..8541747bb 100644 --- a/packages/hardhat/src/types.ts +++ b/packages/hardhat/src/types.ts @@ -1,6 +1,7 @@ export interface TypechainConfig { outDir: string target: string + artifacts?: string[] | undefined alwaysGenerateOverloads: boolean discriminateTypes: boolean tsNocheck: boolean diff --git a/packages/hardhat/test/project.test.ts b/packages/hardhat/test/project.test.ts index ae785ec4e..83b6e2ee6 100644 --- a/packages/hardhat/test/project.test.ts +++ b/packages/hardhat/test/project.test.ts @@ -129,6 +129,86 @@ describe('Typechain x Hardhat', function () { expect(consoleLogMock).toHaveBeenCalledWith(['Successfully generated 14 typings for external artifacts!']) }) }) + + describe('when setting custom artifact glob', () => { + let oldArtifactGlob: string[] | undefined + beforeEach(function () { + oldArtifactGlob = this.hre.config.typechain.artifacts + }) + afterEach(function () { + this.hre.config.typechain.artifacts = oldArtifactGlob + }) + ;[true, false].forEach((forcedCompilation) => { + describe(`when type generation is ${forcedCompilation ? '' : 'not'} forced`, () => { + let subject: () => Promise + beforeEach(async function () { + if (forcedCompilation) { + await this.hre.run('compile', { noTypechain: true }) + } + subject = () => { + if (forcedCompilation) { + return this.hre.run('typechain') + } else { + return this.hre.run('compile') + } + } + }) + + describe('when glob matches some files', () => { + beforeEach(function () { + this.hre.config.typechain.artifacts = ['**/EdgeCases.json'] + }) + + it('includes build artifacts that match the glob', async function () { + const exists = existsSync(this.hre.config.typechain.outDir) + expect(exists).toEqual(false) + + await subject() + + const dir = await readdir(this.hre.config.typechain.outDir) + expect(dir.includes('EdgeCases.ts')).toEqual(true) + }) + + it('excludes build artifacts that do not match the glob', async function () { + const exists = existsSync(this.hre.config.typechain.outDir) + expect(exists).toEqual(false) + + await subject() + + const dir = await readdir(this.hre.config.typechain.outDir) + expect(dir.includes('TestContract.ts')).toEqual(false) + expect(dir.includes('TestContract1.ts')).toEqual(false) + }) + }) + describe('when glob matches no files', () => { + beforeEach(function () { + this.hre.config.typechain.artifacts = ['**/THISDOESNTMATCHANYTHING.json'] + }) + + describe('when no external artifacts are specified', () => { + it('does not generate any types', async function () { + const exists = existsSync(this.hre.config.typechain.outDir) + expect(exists).toEqual(false) + + await subject() + expect(existsSync(this.hre.config.typechain.outDir)).toEqual(false) + }) + }) + + describe('when external artifacts are specified', () => { + it('only generates types for external artifacts', async function () { + const exists = existsSync(this.hre.config.typechain.outDir) + expect(exists).toEqual(false) + + this.hre.config.typechain.externalArtifacts = ['externalArtifacts/*.json'] + await subject() + expect(existsSync(this.hre.config.typechain.outDir)).toEqual(true) + }) + }) + }) + }) + }) + }) }) describe('dontOverrideCompile', function () {