-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Port flatten task to v3 #6068
base: v-next
Are you sure you want to change the base?
Port flatten task to v3 #6068
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
|
hardhatTotal size of the bundle: List of dependencies (sorted by size)
|
@@ -68,6 +68,7 @@ | |||
"@types/debug": "^4.1.4", | |||
"@types/node": "^20.14.9", | |||
"@types/semver": "^7.5.8", | |||
"@types/toposort": "^2.0.7", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have an implementation of topological sort, which we should reuse
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, it's here -
async function reverseTopologicalSort( |
beforeEach(() => { | ||
// Replace console.log and console.warn so we can assert on their output | ||
consoleLogBuffer.length = 0; | ||
consoleWarnBuffer.length = 0; | ||
|
||
console.log = (...args: unknown[]) => { | ||
consoleLogBuffer.push(args.join(" ")); | ||
}; | ||
console.warn = (...args: unknown[]) => { | ||
consoleWarnBuffer.push(args.join(" ")); | ||
}; | ||
}); | ||
|
||
afterEach(() => { | ||
console.log = originalConsoleLog; | ||
console.warn = originalConsoleWarn; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of doing this, the task action can accept these params
print = console.log,
warn = console.warn
which are not exposed to the CLI, nor hooked into it in any way.
Then, to test it, we just need to call the task action directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we wanted to do that, here's an example -
options?: repl.ReplOptions; |
We do, however, assert on the returned values already so it might not be as necessary to inspect the entire stdio. It might still be useful to suppress it though.
Also added a comment about this, but we already have an implementation of top sort.
Single task is the way to go. If we need to make something extensible, we can add hooks.
I guess it's fine for this case.
See the comments.
I think this is ok. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's a good idea to use an internal version of topological sort implementation if we have most of it already in place.
Other than that most of my comments are minor and, as I suspect, mostly directed at the v2 implementation of the task. Feel free to take into account only where it makes sense to you.
As for the testing side of this, I think there are some good candidates for lower level testing - like helper functions, regexes, etc. We don't necesarilly have to add this range of tests in this iteration though. The higher level tests, the E2E ones do seem reasonable to me and do cover the core of the task so I'd be happy to proceed with them.
@@ -68,6 +68,7 @@ | |||
"@types/debug": "^4.1.4", | |||
"@types/node": "^20.14.9", | |||
"@types/semver": "^7.5.8", | |||
"@types/toposort": "^2.0.7", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, it's here -
async function reverseTopologicalSort( |
export interface FlattenActionArguments { | ||
files: string[]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to expose some arguments for testing only, for example stdio streams, you can do it as follows
options?: repl.ReplOptions; |
|
||
export interface FlattenActionResult { | ||
flattened: string; | ||
metadata: FlattenMetadata | null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making metadata optional seems more natural to me.
metadata: FlattenMetadata | null; | |
metadata?: FlattenMetadata; |
|
||
// Return empty string when no files are resolved | ||
if (Array.from(dependencyGraph.getAllFiles()).length === 0) { | ||
return { flattened, metadata: null }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another option would be to return undefined
if there are no files to flatten or even throw an error. I don't have strong preference on one of these three options over the other. Do we know how we expect this task to be consumed programatically? Is it expected to be consumed at all - other than in tests?
async function createHRE() { | ||
return createHardhatRuntimeEnvironment({}, {}, process.cwd()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we just do createHardhatRuntimeEnvironment({})
inline?
beforeEach(() => { | ||
// Replace console.log and console.warn so we can assert on their output | ||
consoleLogBuffer.length = 0; | ||
consoleWarnBuffer.length = 0; | ||
|
||
console.log = (...args: unknown[]) => { | ||
consoleLogBuffer.push(args.join(" ")); | ||
}; | ||
console.warn = (...args: unknown[]) => { | ||
consoleWarnBuffer.push(args.join(" ")); | ||
}; | ||
}); | ||
|
||
afterEach(() => { | ||
console.log = originalConsoleLog; | ||
console.warn = originalConsoleWarn; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we wanted to do that, here's an example -
options?: repl.ReplOptions; |
We do, however, assert on the returned values already so it might not be as necessary to inspect the entire stdio. It might still be useful to suppress it though.
}); | ||
|
||
describe("SPDX licenses and pragma abicoder directives", () => { | ||
describe("Flatten files that dont contain SPDX licenses or pragma directives", () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
describe("Flatten files that dont contain SPDX licenses or pragma directives", () => { | |
describe("Flatten files that don't contain SPDX licenses or pragma directives", () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't really need this file in this fixture project I think.
// This project is compiled from scratch multiple times in the same test, which | ||
// produces a lot of logs. We override this task to omit those logs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the v3 implementation of the task, we don't do the compilation so I don't think we need this either. In fact, I think we should be able to remove all the hardhat.config.js
/hardhat.config.ts
from these projects and still get the tests to work as expected. To be verified though.
Co-authored-by: Piotr Galar <[email protected]>
This PR introduces an implementation for the
flatten
task. Both the implementation and the tests were ported and adapted from v2.Details to point out:
tsort
package was replaced bytoposort
, which has 30x weekly download count and specially, it's typed.FLATTEN
,GET_FLATTENED_SOURCE
,GET_FLATTENED_SOURCE_AND_METADATA
. I wasn't sure there was a need to define more than one task, so I went with this approach. Maybe I could move the printing (contract and warnings) to a separate one, in case just the flattened file and metadata need to be consumed by an external plugin.Closes #5647