From 58535d83c574633e91d9a02798d1134e39fd1fd4 Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Tue, 10 Nov 2020 13:14:05 -0300 Subject: [PATCH 1/4] Add TASK_COMPILE_SOLIDITY_READ_FILE --- .../hardhat-core/src/builtin-tasks/compile.ts | 23 +++++++++++++++++-- .../src/builtin-tasks/task-names.ts | 1 + .../src/internal/solidity/resolver.ts | 7 +++--- .../test/internal/solidity/dependencyGraph.ts | 13 +++++++++-- .../test/internal/solidity/helpers.ts | 8 ++++++- .../test/internal/solidity/resolver.ts | 4 +++- 6 files changed, 46 insertions(+), 10 deletions(-) diff --git a/packages/hardhat-core/src/builtin-tasks/compile.ts b/packages/hardhat-core/src/builtin-tasks/compile.ts index 3e3c928c9c..3f5c1d07f6 100644 --- a/packages/hardhat-core/src/builtin-tasks/compile.ts +++ b/packages/hardhat-core/src/builtin-tasks/compile.ts @@ -1,6 +1,7 @@ import chalk from "chalk"; import { exec } from "child_process"; import debug from "debug"; +import fsExtra from "fs-extra"; import path from "path"; import semver from "semver"; @@ -69,6 +70,7 @@ import { TASK_COMPILE_SOLIDITY_LOG_RUN_COMPILER_END, TASK_COMPILE_SOLIDITY_LOG_RUN_COMPILER_START, TASK_COMPILE_SOLIDITY_MERGE_COMPILATION_JOBS, + TASK_COMPILE_SOLIDITY_READ_FILE, TASK_COMPILE_SOLIDITY_RUN_SOLC, TASK_COMPILE_SOLIDITY_RUN_SOLCJS, } from "./task-names"; @@ -137,6 +139,18 @@ subtask(TASK_COMPILE_SOLIDITY_GET_SOURCE_NAMES) } ); +subtask(TASK_COMPILE_SOLIDITY_READ_FILE) + .addParam("absolutePath", undefined, undefined, types.string) + .setAction( + async ({ absolutePath }: { absolutePath: string }): Promise => { + const content = await fsExtra.readFile(absolutePath, { + encoding: "utf8", + }); + + return content; + } + ); + /** * Receives a list of source names and returns a dependency graph. This task * is responsible for both resolving dependencies (like getting files from @@ -151,10 +165,15 @@ subtask(TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH) sourceNames, solidityFilesCache, }: { sourceNames: string[]; solidityFilesCache?: SolidityFilesCache }, - { config } + { config, run } ): Promise => { const parser = new Parser(solidityFilesCache); - const resolver = new Resolver(config.paths.root, parser); + const resolver = new Resolver( + config.paths.root, + parser, + (absolutePath: string) => + run(TASK_COMPILE_SOLIDITY_READ_FILE, { absolutePath }) + ); const resolvedFiles = await Promise.all( sourceNames.map((sn) => resolver.resolveSourceName(sn)) diff --git a/packages/hardhat-core/src/builtin-tasks/task-names.ts b/packages/hardhat-core/src/builtin-tasks/task-names.ts index 5af7017dd3..8b1ab49d06 100644 --- a/packages/hardhat-core/src/builtin-tasks/task-names.ts +++ b/packages/hardhat-core/src/builtin-tasks/task-names.ts @@ -11,6 +11,7 @@ export const TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS = "compile:solidity:get-source-paths"; export const TASK_COMPILE_SOLIDITY_GET_SOURCE_NAMES = "compile:solidity:get-source-names"; +export const TASK_COMPILE_SOLIDITY_READ_FILE = "compile:solidity:read-file"; export const TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH = "compile:solidity:get-dependency-graph"; export const TASK_COMPILE_SOLIDITY_GET_COMPILATION_JOBS = diff --git a/packages/hardhat-core/src/internal/solidity/resolver.ts b/packages/hardhat-core/src/internal/solidity/resolver.ts index 2e13e38b1f..cc0d63752d 100644 --- a/packages/hardhat-core/src/internal/solidity/resolver.ts +++ b/packages/hardhat-core/src/internal/solidity/resolver.ts @@ -56,7 +56,8 @@ export class ResolvedFile implements IResolvedFile { export class Resolver { constructor( private readonly _projectRoot: string, - private readonly _parser: Parser + private readonly _parser: Parser, + private readonly _readFile: (absolutePath: string) => Promise ) {} /** @@ -294,9 +295,7 @@ export class Resolver { libraryName?: string, libraryVersion?: string ): Promise { - const rawContent = await fsExtra.readFile(absolutePath, { - encoding: "utf8", - }); + const rawContent = await this._readFile(absolutePath); const stats = await fsExtra.stat(absolutePath); const lastModificationDate = new Date(stats.ctime); diff --git a/packages/hardhat-core/test/internal/solidity/dependencyGraph.ts b/packages/hardhat-core/test/internal/solidity/dependencyGraph.ts index fec308ab39..5fb488e67e 100644 --- a/packages/hardhat-core/test/internal/solidity/dependencyGraph.ts +++ b/packages/hardhat-core/test/internal/solidity/dependencyGraph.ts @@ -1,5 +1,6 @@ import { assert } from "chai"; import * as fs from "fs"; +import fsExtra from "fs-extra"; import path from "path"; import { DependencyGraph } from "../../../src/internal/solidity/dependencyGraph"; @@ -119,10 +120,16 @@ describe("Dependency Graph", function () { imports: ["./loop1.sol"], versionPragmas: [], }, + "", new Date() ); - resolver = new Resolver(projectRoot, new Parser()); + resolver = new Resolver( + projectRoot, + new Parser(), + (absolutePath: string) => + fsExtra.readFile(absolutePath, { encoding: "utf8" }) + ); resolver.resolveImport = async (_: ResolvedFile, imported: string) => { switch (imported) { case "./WD.sol": @@ -264,7 +271,9 @@ describe("Dependency Graph", function () { before("Get project root", async function () { localResolver = new Resolver( await getFixtureProjectPath(PROJECT), - new Parser() + new Parser(), + (absolutePath: string) => + fsExtra.readFile(absolutePath, { encoding: "utf8" }) ); }); diff --git a/packages/hardhat-core/test/internal/solidity/helpers.ts b/packages/hardhat-core/test/internal/solidity/helpers.ts index a0a4da1774..359064b357 100644 --- a/packages/hardhat-core/test/internal/solidity/helpers.ts +++ b/packages/hardhat-core/test/internal/solidity/helpers.ts @@ -1,4 +1,5 @@ import * as fs from "fs"; +import fsExtra from "fs-extra"; import path from "path"; import { DependencyGraph } from "../../../src/internal/solidity/dependencyGraph"; @@ -70,7 +71,12 @@ export async function createMockData( return resolvedFile; }); - const resolver = new Resolver(projectRoot, new Parser()); + const resolver = new Resolver( + projectRoot, + new Parser(), + (absolutePath: string) => + fsExtra.readFile(absolutePath, { encoding: "utf8" }) + ); resolver.resolveImport = async (from: ResolvedFile, imported: string) => { const importedFile = importsMap.get(imported); if (importedFile === undefined) { diff --git a/packages/hardhat-core/test/internal/solidity/resolver.ts b/packages/hardhat-core/test/internal/solidity/resolver.ts index 1af146ce28..3f8da6969e 100644 --- a/packages/hardhat-core/test/internal/solidity/resolver.ts +++ b/packages/hardhat-core/test/internal/solidity/resolver.ts @@ -126,7 +126,9 @@ describe("Resolver", function () { }); beforeEach("Init resolver", async function () { - resolver = new Resolver(projectPath, new Parser()); + resolver = new Resolver(projectPath, new Parser(), (absolutePath) => + fsExtra.readFile(absolutePath, { encoding: "utf8" }) + ); }); describe("resolveSourceName", function () { From f4a74d1d75b510c5fb5e0f70614cec5a21c81dcc Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Tue, 10 Nov 2020 14:03:59 -0300 Subject: [PATCH 2/4] Use content hash for cache invalidation --- .../hardhat-core/src/builtin-tasks/compile.ts | 3 +- .../utils/solidity-files-cache.ts | 33 ++++++++++--------- .../src/internal/solidity/parse.ts | 32 ++++++++++++++---- .../src/internal/solidity/resolver.ts | 9 ++++- .../src/types/builtin-tasks/compile.ts | 1 + .../utils/solidity-files-cache.ts | 20 ++++++----- .../solidity/compiler/compiler-input.ts | 2 ++ .../test/internal/solidity/dependencyGraph.ts | 6 ++++ .../test/internal/solidity/helpers.ts | 1 + .../test/internal/solidity/resolver.ts | 4 +++ 10 files changed, 79 insertions(+), 32 deletions(-) diff --git a/packages/hardhat-core/src/builtin-tasks/compile.ts b/packages/hardhat-core/src/builtin-tasks/compile.ts index 3f5c1d07f6..e94a382f44 100644 --- a/packages/hardhat-core/src/builtin-tasks/compile.ts +++ b/packages/hardhat-core/src/builtin-tasks/compile.ts @@ -1204,6 +1204,7 @@ subtask(TASK_COMPILE_SOLIDITY) for (const { file, artifactsEmitted } of artifactsEmittedPerFile) { solidityFilesCache.addFile(file.absolutePath, { lastModificationDate: file.lastModificationDate.valueOf(), + contentHash: file.contentHash, sourceName: file.sourceName, solcConfig: compilationJob.getSolcConfig(), imports: file.content.imports, @@ -1306,7 +1307,7 @@ function needsCompilation( for (const file of job.getResolvedFiles()) { const hasChanged = cache.hasFileChanged( file.absolutePath, - file.lastModificationDate, + file.contentHash, // we only check if the solcConfig is different for files that // emit artifacts job.emitsArtifacts(file) ? job.getSolcConfig() : undefined diff --git a/packages/hardhat-core/src/builtin-tasks/utils/solidity-files-cache.ts b/packages/hardhat-core/src/builtin-tasks/utils/solidity-files-cache.ts index 217f34d36e..572ca1915e 100644 --- a/packages/hardhat-core/src/builtin-tasks/utils/solidity-files-cache.ts +++ b/packages/hardhat-core/src/builtin-tasks/utils/solidity-files-cache.ts @@ -1,3 +1,4 @@ +import debug from "debug"; import fsExtra from "fs-extra"; import * as t from "io-ts"; import type { LoDashStatic } from "lodash"; @@ -6,10 +7,13 @@ import * as path from "path"; import { SOLIDITY_FILES_CACHE_FILENAME } from "../../internal/constants"; import type { ProjectPathsConfig, SolcConfig } from "../../types"; -const FORMAT_VERSION = "hh-sol-cache-1"; +const log = debug("hardhat:core:tasks:compile:cache"); + +const FORMAT_VERSION = "hh-sol-cache-2"; const CacheEntryCodec = t.type({ lastModificationDate: t.number, + contentHash: t.string, sourceName: t.string, solcConfig: t.any, imports: t.array(t.string), @@ -24,6 +28,7 @@ const CacheCodec = t.type({ export interface CacheEntry { lastModificationDate: number; + contentHash: string; sourceName: string; solcConfig: SolcConfig; imports: string[]; @@ -52,30 +57,26 @@ export class SolidityFilesCache { if (result.isRight()) { const solidityFilesCache = new SolidityFilesCache(result.value); - await solidityFilesCache.removeModifiedFiles(); + await solidityFilesCache.removeNonExistingFiles(); return solidityFilesCache; } - // tslint:disable-next-line only-hardhat-error - throw new Error("Couldn't read cache file, try running the clean task"); // TODO use HardhatError + log("There was a problem reading the cache"); + + return new SolidityFilesCache({ + _format: FORMAT_VERSION, + files: {}, + }); } constructor(private _cache: Cache) {} - public async removeModifiedFiles() { - for (const [absolutePath, cachedData] of Object.entries( - this._cache.files - )) { + public async removeNonExistingFiles() { + for (const absolutePath of Object.keys(this._cache.files)) { if (!fsExtra.existsSync(absolutePath)) { this.removeEntry(absolutePath); continue; } - const stats = await fsExtra.stat(absolutePath); - const lastModificationDate = new Date(stats.ctime); - - if (lastModificationDate.valueOf() !== cachedData.lastModificationDate) { - this.removeEntry(absolutePath); - } } } @@ -103,7 +104,7 @@ export class SolidityFilesCache { public hasFileChanged( absolutePath: string, - lastModificationDate: Date, + contentHash: string, solcConfig?: SolcConfig ): boolean { const { isEqual }: LoDashStatic = require("lodash"); @@ -115,7 +116,7 @@ export class SolidityFilesCache { return true; } - if (cacheEntry.lastModificationDate < lastModificationDate.valueOf()) { + if (cacheEntry.contentHash !== contentHash) { return true; } diff --git a/packages/hardhat-core/src/internal/solidity/parse.ts b/packages/hardhat-core/src/internal/solidity/parse.ts index a7bf7b30e7..82d28302b2 100644 --- a/packages/hardhat-core/src/internal/solidity/parse.ts +++ b/packages/hardhat-core/src/internal/solidity/parse.ts @@ -14,8 +14,12 @@ export class Parser { constructor(private _solidityFilesCache?: SolidityFilesCache) {} - public parse(fileContent: string, absolutePath: string): ParsedData { - const cacheResult = this._getFromCache(absolutePath); + public parse( + fileContent: string, + absolutePath: string, + contentHash: string + ): ParsedData { + const cacheResult = this._getFromCache(absolutePath, contentHash); if (cacheResult !== null) { return cacheResult; @@ -55,12 +59,28 @@ export class Parser { return result; } - private _getFromCache(absolutePath: string): ParsedData | null { - const cacheEntry = this._solidityFilesCache?.getEntry(absolutePath); + /** + * Get parsed data from the internal cache, or from the solidity files cache. + * + * Returns null if cannot find it in either one. + */ + private _getFromCache( + absolutePath: string, + contentHash: string + ): ParsedData | null { + if (this._solidityFilesCache === undefined) { + return this._cache.get(absolutePath) ?? null; + } + + const cacheEntry = this._solidityFilesCache.getEntry(absolutePath); + + if (cacheEntry === undefined) { + return this._cache.get(absolutePath) ?? null; + } - if (cacheEntry !== undefined) { - const { imports, versionPragmas } = cacheEntry; + const { imports, versionPragmas } = cacheEntry; + if (cacheEntry.contentHash === contentHash) { return { imports, versionPragmas }; } diff --git a/packages/hardhat-core/src/internal/solidity/resolver.ts b/packages/hardhat-core/src/internal/solidity/resolver.ts index cc0d63752d..31139fcbcf 100644 --- a/packages/hardhat-core/src/internal/solidity/resolver.ts +++ b/packages/hardhat-core/src/internal/solidity/resolver.ts @@ -17,6 +17,7 @@ import { } from "../../utils/source-names"; import { HardhatError } from "../core/errors"; import { ERRORS } from "../core/errors-list"; +import { createNonCryptographicHashBasedIdentifier } from "../util/hash"; import { Parser } from "./parse"; @@ -33,6 +34,7 @@ export class ResolvedFile implements IResolvedFile { public readonly sourceName: string, public readonly absolutePath: string, public readonly content: FileContent, + public readonly contentHash: string, public readonly lastModificationDate: Date, libraryName?: string, libraryVersion?: string @@ -299,7 +301,11 @@ export class Resolver { const stats = await fsExtra.stat(absolutePath); const lastModificationDate = new Date(stats.ctime); - const parsedContent = this._parser.parse(rawContent, absolutePath); + const contentHash = createNonCryptographicHashBasedIdentifier( + Buffer.from(rawContent) + ).toString("hex"); + + const parsedContent = this._parser.parse(rawContent, absolutePath, contentHash); const content = { rawContent, @@ -310,6 +316,7 @@ export class Resolver { sourceName, absolutePath, content, + contentHash, lastModificationDate, libraryName, libraryVersion diff --git a/packages/hardhat-core/src/types/builtin-tasks/compile.ts b/packages/hardhat-core/src/types/builtin-tasks/compile.ts index 764d5c4479..d70a8a33da 100644 --- a/packages/hardhat-core/src/types/builtin-tasks/compile.ts +++ b/packages/hardhat-core/src/types/builtin-tasks/compile.ts @@ -11,6 +11,7 @@ export interface ResolvedFile { // IMPORTANT: Mapped to ctime, NOT mtime. mtime isn't updated when the file // properties (e.g. its name) are changed, only when it's content changes. lastModificationDate: Date; + contentHash: string; getVersionedName(): string; } diff --git a/packages/hardhat-core/test/builtin-tasks/utils/solidity-files-cache.ts b/packages/hardhat-core/test/builtin-tasks/utils/solidity-files-cache.ts index dd242524a8..77e82563cc 100644 --- a/packages/hardhat-core/test/builtin-tasks/utils/solidity-files-cache.ts +++ b/packages/hardhat-core/test/builtin-tasks/utils/solidity-files-cache.ts @@ -5,6 +5,9 @@ import { SolidityFilesCache, } from "../../../src/builtin-tasks/utils/solidity-files-cache"; +const UNMODIFIED_CONTENT_HASH = ""; +const MODIFIED_CONTENT_HASH = ""; + function mockCachedFile( sourceName: string, other: Partial = {} @@ -12,6 +15,7 @@ function mockCachedFile( return { sourceName, lastModificationDate: new Date().valueOf(), + contentHash: UNMODIFIED_CONTENT_HASH, solcConfig: { version: "0.6.6", settings: {} }, imports: [], versionPragmas: [], @@ -66,7 +70,7 @@ describe("SolidityFilesCache", function () { const hasChanged = solidityFilesCache.hasFileChanged( "/path/to/contracts/file.sol", - oneHourAgo, + UNMODIFIED_CONTENT_HASH, solcConfig ); @@ -88,7 +92,7 @@ describe("SolidityFilesCache", function () { const hasChanged = solidityFilesCache.hasFileChanged( "/path/to/contracts/file.sol", - now, + MODIFIED_CONTENT_HASH, solcConfig ); @@ -110,7 +114,7 @@ describe("SolidityFilesCache", function () { const hasChanged = solidityFilesCache.hasFileChanged( "/path/to/contracts/anotherFile.sol", - oneHourAgo, + UNMODIFIED_CONTENT_HASH, solcConfig ); @@ -132,7 +136,7 @@ describe("SolidityFilesCache", function () { const hasChanged = solidityFilesCache.hasFileChanged( "/path/to/contracts/file.sol", - oneHourAgo, + UNMODIFIED_CONTENT_HASH, { version: "0.6.7", settings: {} } ); @@ -154,7 +158,7 @@ describe("SolidityFilesCache", function () { const hasChanged = solidityFilesCache.hasFileChanged( "/path/to/contracts/file.sol", - oneHourAgo, + UNMODIFIED_CONTENT_HASH, { version: "0.6.6", settings: { optimizer: true, runs: 200 } } ); @@ -176,7 +180,7 @@ describe("SolidityFilesCache", function () { const hasChanged = solidityFilesCache.hasFileChanged( "/path/to/contracts/file.sol", - oneHourAgo, + UNMODIFIED_CONTENT_HASH, { version: "0.6.6", settings: {} } ); @@ -198,7 +202,7 @@ describe("SolidityFilesCache", function () { const hasChanged = solidityFilesCache.hasFileChanged( "/path/to/contracts/file.sol", - oneHourAgo + UNMODIFIED_CONTENT_HASH ); assert.isFalse(hasChanged); @@ -219,7 +223,7 @@ describe("SolidityFilesCache", function () { const hasChanged = solidityFilesCache.hasFileChanged( "/path/to/contracts/file.sol", - now + MODIFIED_CONTENT_HASH ); assert.isTrue(hasChanged); diff --git a/packages/hardhat-core/test/internal/solidity/compiler/compiler-input.ts b/packages/hardhat-core/test/internal/solidity/compiler/compiler-input.ts index 03bc814f9c..fded3e9137 100644 --- a/packages/hardhat-core/test/internal/solidity/compiler/compiler-input.ts +++ b/packages/hardhat-core/test/internal/solidity/compiler/compiler-input.ts @@ -48,12 +48,14 @@ describe("compiler-input module", function () { sourceName1, path1, { rawContent: content1, imports: [], versionPragmas: [] }, + "", new Date() ), new ResolvedFile( sourceName2, path2, { rawContent: content2, imports: [], versionPragmas: [] }, + "", new Date() ), ]; diff --git a/packages/hardhat-core/test/internal/solidity/dependencyGraph.ts b/packages/hardhat-core/test/internal/solidity/dependencyGraph.ts index 5fb488e67e..2d5cea4327 100644 --- a/packages/hardhat-core/test/internal/solidity/dependencyGraph.ts +++ b/packages/hardhat-core/test/internal/solidity/dependencyGraph.ts @@ -62,6 +62,7 @@ describe("Dependency Graph", function () { "contracts/WD.sol", path.join(projectRoot, "contracts", "WD.sol"), { rawContent: "no dependecy", imports: [], versionPragmas: [] }, + "", new Date() ); @@ -69,6 +70,7 @@ describe("Dependency Graph", function () { "contracts/WD2.sol", path.join(projectRoot, "contracts", "WD2.sol"), { rawContent: "no dependecy", imports: [], versionPragmas: [] }, + "", new Date() ); @@ -76,6 +78,7 @@ describe("Dependency Graph", function () { "contracts/WD3.sol", path.join(projectRoot, "contracts", "WD3.sol"), { rawContent: "no dependecy", imports: [], versionPragmas: [] }, + "", new Date() ); @@ -87,6 +90,7 @@ describe("Dependency Graph", function () { imports: ["./WD.sol", "./WD2.sol"], versionPragmas: [], }, + "", new Date() ); @@ -98,6 +102,7 @@ describe("Dependency Graph", function () { imports: ["./WD.sol"], versionPragmas: [], }, + "", new Date() ); @@ -109,6 +114,7 @@ describe("Dependency Graph", function () { imports: ["./loop2.sol"], versionPragmas: [], }, + "", new Date() ); diff --git a/packages/hardhat-core/test/internal/solidity/helpers.ts b/packages/hardhat-core/test/internal/solidity/helpers.ts index 359064b357..22c28ca37e 100644 --- a/packages/hardhat-core/test/internal/solidity/helpers.ts +++ b/packages/hardhat-core/test/internal/solidity/helpers.ts @@ -60,6 +60,7 @@ export async function createMockData( .dependencies.map((dependency) => `./${dependency.name}.sol`), versionPragmas: mockFile.versionPragmas, }, + "", new Date(), mockFile.libraryName, mockFile.libraryName === undefined ? undefined : "1.2.3" diff --git a/packages/hardhat-core/test/internal/solidity/resolver.ts b/packages/hardhat-core/test/internal/solidity/resolver.ts index 3f8da6969e..535b210c1a 100644 --- a/packages/hardhat-core/test/internal/solidity/resolver.ts +++ b/packages/hardhat-core/test/internal/solidity/resolver.ts @@ -48,6 +48,7 @@ describe("Resolved file", function () { sourceName, absolutePath, content, + "", lastModificationDate ); @@ -55,6 +56,7 @@ describe("Resolved file", function () { sourceName, absolutePath, content, + "", lastModificationDate, libraryName, libraryVersion @@ -290,6 +292,7 @@ describe("Resolver", function () { imports: [], versionPragmas: [], }, + "", new Date() ); @@ -301,6 +304,7 @@ describe("Resolver", function () { imports: [], versionPragmas: [], }, + "", new Date(), "lib", "1.0.0" From 2097d23660b8216de042d793e266e7363ec3c7fb Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Tue, 10 Nov 2020 16:00:32 -0300 Subject: [PATCH 3/4] Fix linter and build-test --- packages/hardhat-core/src/internal/solidity/resolver.ts | 6 +++++- packages/hardhat-core/test/internal/solidity/parse.ts | 9 +++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/hardhat-core/src/internal/solidity/resolver.ts b/packages/hardhat-core/src/internal/solidity/resolver.ts index 31139fcbcf..83d675c97f 100644 --- a/packages/hardhat-core/src/internal/solidity/resolver.ts +++ b/packages/hardhat-core/src/internal/solidity/resolver.ts @@ -305,7 +305,11 @@ export class Resolver { Buffer.from(rawContent) ).toString("hex"); - const parsedContent = this._parser.parse(rawContent, absolutePath, contentHash); + const parsedContent = this._parser.parse( + rawContent, + absolutePath, + contentHash + ); const content = { rawContent, diff --git a/packages/hardhat-core/test/internal/solidity/parse.ts b/packages/hardhat-core/test/internal/solidity/parse.ts index 5b55224184..5727dd1343 100644 --- a/packages/hardhat-core/test/internal/solidity/parse.ts +++ b/packages/hardhat-core/test/internal/solidity/parse.ts @@ -12,6 +12,7 @@ import "./asd.sol"; pragma experimental v0.5.0; import "lib/asd.sol"; `, + "", "" ); @@ -26,6 +27,7 @@ import * as from "./asd.sol"; pragma experimental v0.5.0; import * as from "lib/asd.sol"; `, + "", "" ); @@ -40,6 +42,7 @@ import {symbol1} from "./asd.sol"; pragma experimental v0.5.0; import {symbol1, symbol2} as from "lib/asd.sol"; `, + "", "" ); @@ -54,6 +57,7 @@ import {symbol1 as s1} as from "./asd.sol"; pragma experimental v0.5.0; import {symbol1 as s1, symbol2} as from "lib/asd.sol"; `, + "", "" ); @@ -77,6 +81,7 @@ import "./1.sol"; ) = [] `, + "", "" ); @@ -95,6 +100,7 @@ import "./1.sol"; } } `, + "", "" ); @@ -113,6 +119,7 @@ import "./Bar.sol;"; contract Foo {} `, + "", "" ); @@ -129,6 +136,7 @@ import "./Bar.sol;"; contract Foo {} `, + "", "" ); @@ -149,6 +157,7 @@ pragma solidity ^0.5.1; contract Qux {} `, + "", "" ); From 6615a031b2fc3e558cc723e2dfa39770b99b6999 Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Wed, 18 Nov 2020 16:47:40 -0300 Subject: [PATCH 4/4] Use content-hash in Parser's internal cache --- .../utils/solidity-files-cache.ts | 7 ++++ .../src/internal/solidity/parse.ts | 32 ++++++++++++------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/packages/hardhat-core/src/builtin-tasks/utils/solidity-files-cache.ts b/packages/hardhat-core/src/builtin-tasks/utils/solidity-files-cache.ts index 572ca1915e..f47fb4d58c 100644 --- a/packages/hardhat-core/src/builtin-tasks/utils/solidity-files-cache.ts +++ b/packages/hardhat-core/src/builtin-tasks/utils/solidity-files-cache.ts @@ -42,6 +42,13 @@ export interface Cache { } export class SolidityFilesCache { + public static createEmpty(): SolidityFilesCache { + return new SolidityFilesCache({ + _format: FORMAT_VERSION, + files: {}, + }); + } + public static async readFromFile( solidityFilesCachePath: string ): Promise { diff --git a/packages/hardhat-core/src/internal/solidity/parse.ts b/packages/hardhat-core/src/internal/solidity/parse.ts index 82d28302b2..87f4875f5e 100644 --- a/packages/hardhat-core/src/internal/solidity/parse.ts +++ b/packages/hardhat-core/src/internal/solidity/parse.ts @@ -1,6 +1,6 @@ import debug from "debug"; -import type { SolidityFilesCache } from "../../builtin-tasks/utils/solidity-files-cache"; +import { SolidityFilesCache } from "../../builtin-tasks/utils/solidity-files-cache"; const log = debug("hardhat:core:solidity:imports"); @@ -11,8 +11,12 @@ interface ParsedData { export class Parser { private _cache = new Map(); + private _solidityFilesCache: SolidityFilesCache; - constructor(private _solidityFilesCache?: SolidityFilesCache) {} + constructor(_solidityFilesCache?: SolidityFilesCache) { + this._solidityFilesCache = + _solidityFilesCache ?? SolidityFilesCache.createEmpty(); + } public parse( fileContent: string, @@ -54,7 +58,7 @@ export class Parser { }; } - this._cache.set(absolutePath, result); + this._cache.set(contentHash, result); return result; } @@ -68,23 +72,27 @@ export class Parser { absolutePath: string, contentHash: string ): ParsedData | null { - if (this._solidityFilesCache === undefined) { - return this._cache.get(absolutePath) ?? null; + const internalCacheEntry = this._cache.get(contentHash); + + if (internalCacheEntry !== undefined) { + return internalCacheEntry; } - const cacheEntry = this._solidityFilesCache.getEntry(absolutePath); + const solidityFilesCacheEntry = this._solidityFilesCache.getEntry( + absolutePath + ); - if (cacheEntry === undefined) { - return this._cache.get(absolutePath) ?? null; + if (solidityFilesCacheEntry === undefined) { + return null; } - const { imports, versionPragmas } = cacheEntry; + const { imports, versionPragmas } = solidityFilesCacheEntry; - if (cacheEntry.contentHash === contentHash) { - return { imports, versionPragmas }; + if (solidityFilesCacheEntry.contentHash !== contentHash) { + return null; } - return this._cache.get(absolutePath) ?? null; + return { imports, versionPragmas }; } }