hardhat 3.5.0 → 3.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.d.ts +1 -4
- package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.js +1 -11
- package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.js.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/warning-suppression.d.ts +6 -10
- package/dist/src/internal/builtin-plugins/solidity/build-system/warning-suppression.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/warning-suppression.js +54 -43
- package/dist/src/internal/builtin-plugins/solidity/build-system/warning-suppression.js.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/hook-handlers/hre.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/hook-handlers/hre.js +2 -1
- package/dist/src/internal/builtin-plugins/solidity/hook-handlers/hre.js.map +1 -1
- package/dist/src/internal/cli/error-handler.d.ts +11 -2
- package/dist/src/internal/cli/error-handler.d.ts.map +1 -1
- package/dist/src/internal/cli/error-handler.js +72 -46
- package/dist/src/internal/cli/error-handler.js.map +1 -1
- package/dist/src/internal/cli/init/init.d.ts.map +1 -1
- package/dist/src/internal/cli/init/init.js +5 -3
- package/dist/src/internal/cli/init/init.js.map +1 -1
- package/dist/src/internal/cli/init/package-manager.d.ts +7 -1
- package/dist/src/internal/cli/init/package-manager.d.ts.map +1 -1
- package/dist/src/internal/cli/init/package-manager.js +14 -2
- package/dist/src/internal/cli/init/package-manager.js.map +1 -1
- package/dist/src/internal/cli/main.js +1 -1
- package/dist/src/internal/cli/main.js.map +1 -1
- package/dist/src/internal/cli/telemetry/error-classification/classifier.d.ts +2 -1
- package/dist/src/internal/cli/telemetry/error-classification/classifier.d.ts.map +1 -1
- package/dist/src/internal/cli/telemetry/error-classification/classifier.js +2 -1
- package/dist/src/internal/cli/telemetry/error-classification/classifier.js.map +1 -1
- package/dist/src/internal/using-hardhat2-plugin-errors.d.ts.map +1 -1
- package/dist/src/internal/using-hardhat2-plugin-errors.js +8 -11
- package/dist/src/internal/using-hardhat2-plugin-errors.js.map +1 -1
- package/package.json +1 -1
- package/src/internal/builtin-plugins/solidity/build-system/build-system.ts +2 -15
- package/src/internal/builtin-plugins/solidity/build-system/warning-suppression.ts +81 -59
- package/src/internal/builtin-plugins/solidity/hook-handlers/hre.ts +2 -1
- package/src/internal/cli/error-handler.ts +103 -72
- package/src/internal/cli/init/init.ts +5 -0
- package/src/internal/cli/init/package-manager.ts +18 -1
- package/src/internal/cli/main.ts +1 -1
- package/src/internal/cli/telemetry/error-classification/classifier.ts +2 -1
- package/src/internal/using-hardhat2-plugin-errors.ts +8 -11
- package/templates/hardhat-3/01-node-test-runner-viem/package.json +2 -2
- package/templates/hardhat-3/02-mocha-ethers/package.json +1 -1
- package/templates/hardhat-3/03-minimal/package.json +1 -1
|
@@ -10,21 +10,18 @@ export class UsingHardhat2PluginError extends CustomError {
|
|
|
10
10
|
if (callerPath !== undefined) {
|
|
11
11
|
message = `You are trying to use a Hardhat 2 plugin in a Hardhat 3 project.
|
|
12
12
|
|
|
13
|
-
This file is part of a Hardhat 2 plugin calling an API that was removed in Hardhat 3: ${styleText("bold", callerPath)}
|
|
14
|
-
|
|
15
|
-
Please read https://hardhat.org/migrate-from-hardhat2 to learn how to migrate your project to Hardhat 3.
|
|
16
|
-
`;
|
|
13
|
+
This file is part of a Hardhat 2 plugin calling an API that was removed in Hardhat 3: ${styleText("bold", callerPath)}`;
|
|
17
14
|
}
|
|
18
15
|
else {
|
|
19
|
-
message = `You are trying to use a Hardhat 2 plugin in a Hardhat 3 project
|
|
20
|
-
|
|
21
|
-
Check the stack trace below to identify which plugin is causing this.
|
|
22
|
-
|
|
23
|
-
Please read https://hardhat.org/migrate-from-hardhat2 to learn how to migrate your project to Hardhat 3.
|
|
24
|
-
`;
|
|
16
|
+
message = `You are trying to use a Hardhat 2 plugin in a Hardhat 3 project.`;
|
|
25
17
|
}
|
|
26
18
|
super(message);
|
|
27
|
-
|
|
19
|
+
// Use a non-enumerable property so that `console.error(error)` does not
|
|
20
|
+
// print `{ callerRelativePath: '…' }` after the stack trace.
|
|
21
|
+
Object.defineProperty(this, "callerRelativePath", {
|
|
22
|
+
value: callerPath,
|
|
23
|
+
enumerable: false,
|
|
24
|
+
});
|
|
28
25
|
}
|
|
29
26
|
}
|
|
30
27
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"using-hardhat2-plugin-errors.js","sourceRoot":"","sources":["../../../src/internal/using-hardhat2-plugin-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAElE,MAAM,OAAO,wBAAyB,SAAQ,WAAW;IACvC,kBAAkB,CAAqB;IACvD;QACE,MAAM,UAAU,GAAG,qBAAqB,EAAE,CAAC;QAE3C,IAAI,OAAe,CAAC;QACpB,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,OAAO,GAAG;;wFAEwE,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC
|
|
1
|
+
{"version":3,"file":"using-hardhat2-plugin-errors.js","sourceRoot":"","sources":["../../../src/internal/using-hardhat2-plugin-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAElE,MAAM,OAAO,wBAAyB,SAAQ,WAAW;IACvC,kBAAkB,CAAqB;IACvD;QACE,MAAM,UAAU,GAAG,qBAAqB,EAAE,CAAC;QAE3C,IAAI,OAAe,CAAC;QACpB,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,OAAO,GAAG;;wFAEwE,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC;QACpH,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,kEAAkE,CAAC;QAC/E,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,wEAAwE;QACxE,6DAA6D;QAC7D,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,oBAAoB,EAAE;YAChD,KAAK,EAAE,UAAU;YACjB,UAAU,EAAE,KAAK;SAClB,CAAC,CAAC;IACL,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAgB,CAAC;IACrD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,CAAC;QAChC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,OAAO,SAAS,CAAC;QACnB,CAAC;QAED;;;;;;;;WAQG;QACH,MAAM,sBAAsB,GAC1B,iDAAiD,CAAC;QAEpD,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC9D,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;YAC7C,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,IAAI,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAExB,4CAA4C;QAC5C,IAAI,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACnC,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,6BAA6B;IAC3C;kEAC8D;IAC9D,MAAM,IAAI,wBAAwB,EAAE,CAAC;AACvC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hardhat",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.1",
|
|
4
4
|
"description": "Hardhat is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.",
|
|
5
5
|
"homepage": "https://hardhat.org",
|
|
6
6
|
"repository": {
|
|
@@ -95,21 +95,6 @@ export function isSolcSolidityCompilerConfig(
|
|
|
95
95
|
return config.type === undefined || config.type === "solc";
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
// Compiler warnings to suppress from build output.
|
|
99
|
-
// Each rule specifies a warning message and the source file it applies to.
|
|
100
|
-
// This allows suppressing known warnings from internal files (e.g., console.sol)
|
|
101
|
-
// while still showing the same warning type from user code.
|
|
102
|
-
export const SUPPRESSED_WARNINGS: Array<{
|
|
103
|
-
message: string;
|
|
104
|
-
sourceFile: string;
|
|
105
|
-
}> = [
|
|
106
|
-
{
|
|
107
|
-
message:
|
|
108
|
-
"Natspec memory-safe-assembly special comment for inline assembly is deprecated and scheduled for removal. Use the memory-safe block annotation instead.",
|
|
109
|
-
sourceFile: path.normalize("hardhat/console.sol"),
|
|
110
|
-
},
|
|
111
|
-
];
|
|
112
|
-
|
|
113
98
|
interface CompilationResult {
|
|
114
99
|
compilationJob: CompilationJob;
|
|
115
100
|
compilerOutput: CompilerOutput;
|
|
@@ -123,6 +108,7 @@ export interface SolidityBuildSystemOptions {
|
|
|
123
108
|
readonly artifactsPath: string;
|
|
124
109
|
readonly cachePath: string;
|
|
125
110
|
readonly solidityTestsPath: string;
|
|
111
|
+
readonly coverage: boolean;
|
|
126
112
|
}
|
|
127
113
|
|
|
128
114
|
/**
|
|
@@ -1417,6 +1403,7 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem {
|
|
|
1417
1403
|
msg,
|
|
1418
1404
|
this.#options.solidityTestsPath,
|
|
1419
1405
|
this.#options.projectRoot,
|
|
1406
|
+
this.#options.coverage,
|
|
1420
1407
|
);
|
|
1421
1408
|
}
|
|
1422
1409
|
|
|
@@ -1,97 +1,119 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
| {
|
|
24
|
-
message: string;
|
|
25
|
-
scope: "test-files";
|
|
26
|
-
}
|
|
27
|
-
> = [
|
|
3
|
+
import { COVERAGE_LIBRARY_FILE_NAME } from "@nomicfoundation/edr";
|
|
4
|
+
|
|
5
|
+
export const NATSPEC_MEMORY_SAFE_ASSEMBLY_WARNING =
|
|
6
|
+
"Natspec memory-safe-assembly special comment for inline assembly is deprecated and scheduled for removal. Use the memory-safe block annotation instead.";
|
|
7
|
+
export const SPDX_WARNING = "SPDX license identifier not provided";
|
|
8
|
+
export const PRAGMA_WARNING =
|
|
9
|
+
"Source file does not specify required compiler version";
|
|
10
|
+
const CONTRACT_SIZE_WARNING = "Contract code size is";
|
|
11
|
+
|
|
12
|
+
// Suppression rules are grouped by scope. Each array has its own match logic
|
|
13
|
+
// in `shouldSuppressWarning` function; add new entries to the array that fits, or add
|
|
14
|
+
// a new array + block for a new scope.
|
|
15
|
+
|
|
16
|
+
// Warnings tied to a specific internal file (e.g. console.sol). Suppressed
|
|
17
|
+
// only when the warning points at that file.
|
|
18
|
+
const SPECIFIC_FILE_RULES: ReadonlyArray<{
|
|
19
|
+
message: string;
|
|
20
|
+
filePath: string;
|
|
21
|
+
}> = [
|
|
28
22
|
{
|
|
29
|
-
message:
|
|
30
|
-
"Natspec memory-safe-assembly special comment for inline assembly is deprecated and scheduled for removal. Use the memory-safe block annotation instead.",
|
|
31
|
-
scope: "specific-file",
|
|
23
|
+
message: NATSPEC_MEMORY_SAFE_ASSEMBLY_WARNING,
|
|
32
24
|
// Normalize to handle different OS path separators
|
|
33
25
|
filePath: path.normalize("hardhat/console.sol"),
|
|
34
26
|
},
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
// Warnings acceptable in test files. Suppressed when the warning points at a
|
|
30
|
+
// file ending in `.t.sol` or inside the configured Solidity test directory.
|
|
31
|
+
const TEST_FILE_WARNING_MESSAGES: readonly string[] = [
|
|
32
|
+
SPDX_WARNING,
|
|
33
|
+
PRAGMA_WARNING,
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
// Warnings suppressed only when running with `--coverage`. An entry with no
|
|
37
|
+
// `filePath` matches the message anywhere (e.g. contract-size warnings that
|
|
38
|
+
// fire on user files as a side effect of instrumentation); an entry with a
|
|
39
|
+
// `filePath` only matches when the diagnostic also points at that file
|
|
40
|
+
// (e.g. the injected coverage library file, which users can't edit).
|
|
41
|
+
const COVERAGE_MODE_RULES: ReadonlyArray<{
|
|
42
|
+
message: string;
|
|
43
|
+
filePath?: string;
|
|
44
|
+
}> = [
|
|
45
|
+
{ message: CONTRACT_SIZE_WARNING },
|
|
35
46
|
{
|
|
36
|
-
message:
|
|
37
|
-
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
message: "Source file does not specify required compiler version",
|
|
41
|
-
scope: "test-files",
|
|
47
|
+
message: NATSPEC_MEMORY_SAFE_ASSEMBLY_WARNING,
|
|
48
|
+
filePath: COVERAGE_LIBRARY_FILE_NAME,
|
|
42
49
|
},
|
|
43
50
|
];
|
|
44
51
|
|
|
45
52
|
/**
|
|
46
|
-
* Determines if a compiler warning should be suppressed
|
|
53
|
+
* Determines if a compiler warning should be suppressed.
|
|
47
54
|
*
|
|
48
55
|
* @param errorMessage - The formatted error message from the compiler
|
|
49
56
|
* @param absoluteSolidityTestsPath - Absolute path to the Solidity test directory
|
|
50
57
|
* @param absoluteProjectRoot - Absolute path to the project root
|
|
58
|
+
* @param coverage - Whether the build is running with `--coverage` enabled
|
|
51
59
|
* @returns true if the warning should be suppressed, false otherwise
|
|
52
60
|
*/
|
|
53
61
|
export function shouldSuppressWarning(
|
|
54
62
|
errorMessage: string,
|
|
55
63
|
absoluteSolidityTestsPath: string,
|
|
56
64
|
absoluteProjectRoot: string,
|
|
65
|
+
coverage: boolean,
|
|
57
66
|
): boolean {
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return SUPPRESSED_WARNINGS.some((rule) => {
|
|
70
|
-
if (!errorMessage.includes(rule.message)) {
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
67
|
+
// Warnings suppressed only when running with `--coverage`.
|
|
68
|
+
if (
|
|
69
|
+
coverage &&
|
|
70
|
+
COVERAGE_MODE_RULES.some(
|
|
71
|
+
(rule) =>
|
|
72
|
+
errorMessage.includes(rule.message) &&
|
|
73
|
+
(rule.filePath === undefined || errorMessage.includes(rule.filePath)),
|
|
74
|
+
)
|
|
75
|
+
) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
73
78
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
79
|
+
// Warnings tied to a specific internal file (e.g. console.sol).
|
|
80
|
+
if (
|
|
81
|
+
SPECIFIC_FILE_RULES.some(
|
|
82
|
+
(rule) =>
|
|
83
|
+
errorMessage.includes(rule.message) &&
|
|
84
|
+
errorMessage.includes(rule.filePath),
|
|
85
|
+
)
|
|
86
|
+
) {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
77
89
|
|
|
78
|
-
|
|
90
|
+
// Warnings allowed in test files.
|
|
91
|
+
if (TEST_FILE_WARNING_MESSAGES.some((m) => errorMessage.includes(m))) {
|
|
79
92
|
// Test files are identified by:
|
|
80
93
|
// - Ending in .t.sol (e.g., Counter.t.sol)
|
|
81
94
|
// - Being inside the configured Solidity test directory
|
|
82
|
-
|
|
83
95
|
if (/\.t\.sol(:|$|\s)/.test(errorMessage)) {
|
|
84
96
|
return true;
|
|
85
97
|
}
|
|
86
98
|
|
|
87
|
-
//
|
|
99
|
+
// Compute relative path from project root to test directory.
|
|
100
|
+
// Example:
|
|
101
|
+
// absoluteSolidityTestsPath: /workspaces/hardhat-4/packages/example-project/test/contracts
|
|
102
|
+
// absoluteProjectRoot: /workspaces/hardhat-4/packages/example-project
|
|
103
|
+
// relativeTestPath: test/contracts/ - note the addition of the `/`
|
|
104
|
+
// to avoid partial matches, e.g.: test/contractsUtils/
|
|
105
|
+
const relativeTestPath = path.join(
|
|
106
|
+
path.relative(absoluteProjectRoot, absoluteSolidityTestsPath),
|
|
107
|
+
"/",
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
// Extract file path from error message.
|
|
88
111
|
// Format: "Warning: message\n --> path/to/file.sol:line:column:"
|
|
89
112
|
const pathMatches = errorMessage.match(/-->\s+([^\s:]+\.sol)/);
|
|
90
|
-
|
|
91
113
|
if (pathMatches !== null) {
|
|
92
114
|
return pathMatches[1].includes(relativeTestPath);
|
|
93
115
|
}
|
|
116
|
+
}
|
|
94
117
|
|
|
95
|
-
|
|
96
|
-
});
|
|
118
|
+
return false;
|
|
97
119
|
}
|
|
@@ -152,7 +152,7 @@ class LazySolidityBuildSystem implements SolidityBuildSystem {
|
|
|
152
152
|
|
|
153
153
|
export default async (): Promise<Partial<HardhatRuntimeEnvironmentHooks>> => {
|
|
154
154
|
return {
|
|
155
|
-
created: async (
|
|
155
|
+
created: async (context, hre) => {
|
|
156
156
|
hre.solidity = new LazySolidityBuildSystem(hre.hooks, {
|
|
157
157
|
solidityConfig: hre.config.solidity,
|
|
158
158
|
projectRoot: hre.config.paths.root,
|
|
@@ -160,6 +160,7 @@ export default async (): Promise<Partial<HardhatRuntimeEnvironmentHooks>> => {
|
|
|
160
160
|
artifactsPath: hre.config.paths.artifacts,
|
|
161
161
|
cachePath: hre.config.paths.cache,
|
|
162
162
|
solidityTestsPath: hre.config.paths.tests.solidity,
|
|
163
|
+
coverage: context.globalOptions.coverage,
|
|
163
164
|
});
|
|
164
165
|
},
|
|
165
166
|
};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type * as ClassifierT from "./telemetry/error-classification/classifier.js";
|
|
2
|
+
|
|
1
3
|
import { styleText } from "node:util";
|
|
2
4
|
|
|
3
5
|
import {
|
|
@@ -6,19 +8,24 @@ import {
|
|
|
6
8
|
} from "@nomicfoundation/hardhat-errors";
|
|
7
9
|
|
|
8
10
|
import { HARDHAT_NAME, HARDHAT_WEBSITE_URL } from "../constants.js";
|
|
9
|
-
|
|
11
|
+
|
|
12
|
+
// The classifier may import many unrelated things top-level to do its job, so
|
|
13
|
+
// we load it lazily.
|
|
14
|
+
let classifierModule: typeof ClassifierT | undefined;
|
|
10
15
|
|
|
11
16
|
/**
|
|
12
17
|
* The different categories of errors that can be handled by hardhat cli.
|
|
13
18
|
* Each category has a different way of being formatted and displayed.
|
|
14
19
|
* To add new categories, add a new entry to this enum and update the
|
|
15
|
-
* {@link getErrorWithCategory} and
|
|
16
|
-
* accordingly.
|
|
20
|
+
* {@link getErrorWithCategory} function and the switch inside
|
|
21
|
+
* {@link printErrorMessages} accordingly.
|
|
17
22
|
*/
|
|
18
23
|
enum ErrorCategory {
|
|
19
24
|
HARDHAT = "HARDHAT",
|
|
20
25
|
PLUGIN = "PLUGIN",
|
|
21
26
|
COMMUNITY_PLUGIN = "COMMUNITY_PLUGIN",
|
|
27
|
+
HH2_TO_HH3_MIGRATION = "HH2_TO_HH3_MIGRATION",
|
|
28
|
+
CJS_TO_ESM_MIGRATION = "CJS_TO_ESM_MIGRATION",
|
|
22
29
|
OTHER = "OTHER",
|
|
23
30
|
}
|
|
24
31
|
|
|
@@ -35,55 +42,91 @@ type ErrorWithCategory =
|
|
|
35
42
|
category: ErrorCategory.COMMUNITY_PLUGIN;
|
|
36
43
|
categorizedError: HardhatPluginError;
|
|
37
44
|
}
|
|
45
|
+
| {
|
|
46
|
+
category: ErrorCategory.HH2_TO_HH3_MIGRATION;
|
|
47
|
+
categorizedError: Error;
|
|
48
|
+
}
|
|
49
|
+
| {
|
|
50
|
+
category: ErrorCategory.CJS_TO_ESM_MIGRATION;
|
|
51
|
+
categorizedError: Error;
|
|
52
|
+
}
|
|
38
53
|
| {
|
|
39
54
|
category: ErrorCategory.OTHER;
|
|
40
55
|
categorizedError: unknown;
|
|
41
56
|
};
|
|
42
57
|
|
|
43
|
-
/**
|
|
44
|
-
* The different messages that can be displayed for each category of errors.
|
|
45
|
-
* - `formattedErrorMessage`: the main error message that is always displayed.
|
|
46
|
-
* - `showMoreInfoMessage`: an optional message that can be displayed to
|
|
47
|
-
* provide more information about the error. It is only displayed when stack
|
|
48
|
-
* traces are hidden.
|
|
49
|
-
* - `postErrorStackTraceMessage` an optional message that can be displayed
|
|
50
|
-
* after the stack trace. It is only displayed when stack traces are shown.
|
|
51
|
-
*/
|
|
52
|
-
interface ErrorMessages {
|
|
53
|
-
formattedErrorMessage: string;
|
|
54
|
-
showMoreInfoMessage?: string;
|
|
55
|
-
postErrorStackTraceMessage?: string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
58
|
/**
|
|
59
59
|
* Formats and logs error messages based on the category the error belongs to.
|
|
60
60
|
*
|
|
61
|
+
* For each category, we produce up to three pieces:
|
|
62
|
+
* - `formattedErrorMessage`: the main error message that is always displayed.
|
|
63
|
+
* - `showMoreInfoMessage`: an optional message that points the user at more
|
|
64
|
+
* info. It is only displayed when the stack trace is hidden.
|
|
65
|
+
* - `postErrorStackTraceMessage`: an optional message that is displayed after
|
|
66
|
+
* the stack trace.
|
|
67
|
+
*
|
|
61
68
|
* @param error the error to handle. Supported categories are defined in
|
|
62
69
|
* {@link ErrorCategory}.
|
|
63
70
|
* @param shouldShowStackTraces whether to show stack traces or not. If true,
|
|
64
71
|
* the stack trace is always shown. If false, the stack trace is only shown for
|
|
65
|
-
* errors of category {@link ErrorCategory.OTHER}
|
|
72
|
+
* errors of category {@link ErrorCategory.OTHER},
|
|
73
|
+
* {@link ErrorCategory.HH2_TO_HH3_MIGRATION}, and
|
|
74
|
+
* {@link ErrorCategory.CJS_TO_ESM_MIGRATION}.
|
|
66
75
|
* @param print the function used to print the error message, defaults to
|
|
67
76
|
* `console.error`. Useful for testing to capture error messages.
|
|
68
77
|
*/
|
|
69
|
-
export function printErrorMessages(
|
|
78
|
+
export async function printErrorMessages(
|
|
70
79
|
error: Error,
|
|
71
80
|
shouldShowStackTraces: boolean = false,
|
|
72
81
|
print: (message: string | Error) => void = console.error,
|
|
73
|
-
): void {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
82
|
+
): Promise<void> {
|
|
83
|
+
const { category, categorizedError } = await getErrorWithCategory(error);
|
|
84
|
+
|
|
85
|
+
let formattedErrorMessage: string;
|
|
86
|
+
let showMoreInfoMessage: string | undefined;
|
|
87
|
+
let postErrorStackTraceMessage: string | undefined;
|
|
88
|
+
|
|
89
|
+
switch (category) {
|
|
90
|
+
case ErrorCategory.HARDHAT:
|
|
91
|
+
formattedErrorMessage = `${styleText(["red", "bold"], `Error ${categorizedError.errorCode}:`)} ${categorizedError.formattedMessage}`;
|
|
92
|
+
showMoreInfoMessage = `For more info go to ${HARDHAT_WEBSITE_URL}${categorizedError.errorCode} or run ${HARDHAT_NAME} with --show-stack-traces`;
|
|
93
|
+
break;
|
|
94
|
+
case ErrorCategory.PLUGIN:
|
|
95
|
+
formattedErrorMessage = `${styleText(["red", "bold"], `Error ${categorizedError.errorCode} in plugin ${categorizedError.pluginId}:`)} ${categorizedError.formattedMessage}`;
|
|
96
|
+
showMoreInfoMessage = `For more info go to ${HARDHAT_WEBSITE_URL}${categorizedError.errorCode} or run ${HARDHAT_NAME} with --show-stack-traces`;
|
|
97
|
+
break;
|
|
98
|
+
case ErrorCategory.COMMUNITY_PLUGIN:
|
|
99
|
+
formattedErrorMessage = `${styleText(["red", "bold"], `Error in community plugin ${categorizedError.pluginId}:`)} ${categorizedError.message}`;
|
|
100
|
+
showMoreInfoMessage = `For more info run ${HARDHAT_NAME} with --show-stack-traces`;
|
|
101
|
+
break;
|
|
102
|
+
case ErrorCategory.HH2_TO_HH3_MIGRATION:
|
|
103
|
+
formattedErrorMessage = styleText(
|
|
104
|
+
["red", "bold"],
|
|
105
|
+
`Hardhat 3 migration error:`,
|
|
106
|
+
);
|
|
107
|
+
postErrorStackTraceMessage = `It looks like you are migrating from Hardhat 2 to Hardhat 3. The following error often shows up during this kind of migration.\nPlease read https://hardhat.org/migrate-from-hardhat2 to learn how to migrate your project to Hardhat 3.`;
|
|
108
|
+
break;
|
|
109
|
+
case ErrorCategory.CJS_TO_ESM_MIGRATION:
|
|
110
|
+
formattedErrorMessage = styleText(
|
|
111
|
+
["red", "bold"],
|
|
112
|
+
`Hardhat 3 migration error:`,
|
|
113
|
+
);
|
|
114
|
+
postErrorStackTraceMessage = `It looks like you are migrating from CommonJS to ESM. The following error often shows up during this kind of migration.\nPlease read https://hardhat.org/migrate-to-esm to learn how to migrate your project to ESM.`;
|
|
115
|
+
break;
|
|
116
|
+
case ErrorCategory.OTHER:
|
|
117
|
+
formattedErrorMessage = styleText(
|
|
118
|
+
["red", "bold"],
|
|
119
|
+
`An unexpected error occurred:`,
|
|
120
|
+
);
|
|
121
|
+
postErrorStackTraceMessage = `If you think this is a bug in Hardhat, please report it here: ${HARDHAT_WEBSITE_URL}report-bug`;
|
|
122
|
+
break;
|
|
77
123
|
}
|
|
78
124
|
|
|
79
125
|
const showStackTraces =
|
|
80
126
|
shouldShowStackTraces ||
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
showMoreInfoMessage,
|
|
85
|
-
postErrorStackTraceMessage,
|
|
86
|
-
} = getErrorMessages(error);
|
|
127
|
+
category === ErrorCategory.OTHER ||
|
|
128
|
+
category === ErrorCategory.HH2_TO_HH3_MIGRATION ||
|
|
129
|
+
category === ErrorCategory.CJS_TO_ESM_MIGRATION;
|
|
87
130
|
|
|
88
131
|
print(formattedErrorMessage);
|
|
89
132
|
|
|
@@ -100,7 +143,7 @@ export function printErrorMessages(
|
|
|
100
143
|
}
|
|
101
144
|
}
|
|
102
145
|
|
|
103
|
-
function getErrorWithCategory(error: Error): ErrorWithCategory {
|
|
146
|
+
async function getErrorWithCategory(error: Error): Promise<ErrorWithCategory> {
|
|
104
147
|
if (HardhatError.isHardhatError(error)) {
|
|
105
148
|
if (error.pluginId === undefined) {
|
|
106
149
|
return {
|
|
@@ -122,49 +165,37 @@ function getErrorWithCategory(error: Error): ErrorWithCategory {
|
|
|
122
165
|
};
|
|
123
166
|
}
|
|
124
167
|
|
|
168
|
+
if (classifierModule === undefined) {
|
|
169
|
+
classifierModule = await import(
|
|
170
|
+
"./telemetry/error-classification/classifier.js"
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Pass `ignoreDevelopmentTimeFilter=true` so the migration footer also shows
|
|
175
|
+
// when hardhat is run from inside its own monorepo — the dev-time filter is
|
|
176
|
+
// a telemetry concern (don't report to Sentry), unrelated to display routing.
|
|
177
|
+
const classifierCategory = classifierModule.classifyError(error, true);
|
|
178
|
+
if (
|
|
179
|
+
classifierCategory ===
|
|
180
|
+
classifierModule.ErrorCategory.HH2_TO_HH3_MIGRATION_ERROR
|
|
181
|
+
) {
|
|
182
|
+
return {
|
|
183
|
+
category: ErrorCategory.HH2_TO_HH3_MIGRATION,
|
|
184
|
+
categorizedError: error,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
if (
|
|
188
|
+
classifierCategory ===
|
|
189
|
+
classifierModule.ErrorCategory.CJS_TO_ESM_MIGRATION_ERROR
|
|
190
|
+
) {
|
|
191
|
+
return {
|
|
192
|
+
category: ErrorCategory.CJS_TO_ESM_MIGRATION,
|
|
193
|
+
categorizedError: error,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
125
197
|
return {
|
|
126
198
|
category: ErrorCategory.OTHER,
|
|
127
199
|
categorizedError: error,
|
|
128
200
|
};
|
|
129
201
|
}
|
|
130
|
-
|
|
131
|
-
function getErrorMessages(error: Error): ErrorMessages {
|
|
132
|
-
const { category, categorizedError } = getErrorWithCategory(error);
|
|
133
|
-
switch (category) {
|
|
134
|
-
case ErrorCategory.HARDHAT:
|
|
135
|
-
return {
|
|
136
|
-
formattedErrorMessage: `${styleText(["red", "bold"], `Error ${categorizedError.errorCode}:`)} ${categorizedError.formattedMessage}`,
|
|
137
|
-
showMoreInfoMessage: `For more info go to ${HARDHAT_WEBSITE_URL}${categorizedError.errorCode} or run ${HARDHAT_NAME} with --show-stack-traces`,
|
|
138
|
-
};
|
|
139
|
-
case ErrorCategory.PLUGIN:
|
|
140
|
-
return {
|
|
141
|
-
formattedErrorMessage: `${styleText(["red", "bold"], `Error ${categorizedError.errorCode} in plugin ${categorizedError.pluginId}:`)} ${categorizedError.formattedMessage}`,
|
|
142
|
-
showMoreInfoMessage: `For more info go to ${HARDHAT_WEBSITE_URL}${categorizedError.errorCode} or run ${HARDHAT_NAME} with --show-stack-traces`,
|
|
143
|
-
};
|
|
144
|
-
case ErrorCategory.COMMUNITY_PLUGIN:
|
|
145
|
-
return {
|
|
146
|
-
formattedErrorMessage: `${styleText(["red", "bold"], `Error in community plugin ${categorizedError.pluginId}:`)} ${categorizedError.message}`,
|
|
147
|
-
showMoreInfoMessage: `For more info run ${HARDHAT_NAME} with --show-stack-traces`,
|
|
148
|
-
};
|
|
149
|
-
case ErrorCategory.OTHER:
|
|
150
|
-
return {
|
|
151
|
-
formattedErrorMessage: styleText(
|
|
152
|
-
["red", "bold"],
|
|
153
|
-
`An unexpected error occurred:`,
|
|
154
|
-
),
|
|
155
|
-
postErrorStackTraceMessage: `If you think this is a bug in Hardhat, please report it here: ${HARDHAT_WEBSITE_URL}report-bug`,
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
function printUsingHardhat2Error(
|
|
160
|
-
error: UsingHardhat2PluginError,
|
|
161
|
-
print: (message: string | Error) => void = console.error,
|
|
162
|
-
): void {
|
|
163
|
-
print(styleText(["red", "bold"], `Hardhat 3 installation error:`));
|
|
164
|
-
print("");
|
|
165
|
-
if (error.callerRelativePath !== undefined) {
|
|
166
|
-
print(error.message);
|
|
167
|
-
} else {
|
|
168
|
-
print(error.stack);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
@@ -35,6 +35,7 @@ import { sendErrorTelemetry } from "../telemetry/error-reporter/reporter.js";
|
|
|
35
35
|
import {
|
|
36
36
|
getDevDependenciesInstallationCommand,
|
|
37
37
|
getPackageManager,
|
|
38
|
+
getVersion,
|
|
38
39
|
installsPeerDependenciesByDefault,
|
|
39
40
|
} from "./package-manager.js";
|
|
40
41
|
import {
|
|
@@ -694,6 +695,8 @@ export async function installProjectDependencies({
|
|
|
694
695
|
);
|
|
695
696
|
|
|
696
697
|
const packageManager = getPackageManager();
|
|
698
|
+
const packageManagerVersion = await getVersion(workspace, packageManager);
|
|
699
|
+
const packageManagerMajorVersion = packageManagerVersion?.[0];
|
|
697
700
|
|
|
698
701
|
// Find the template dev dependencies that are not already installed
|
|
699
702
|
const templateDependencies = template.packageJson.devDependencies ?? {};
|
|
@@ -730,6 +733,7 @@ export async function installProjectDependencies({
|
|
|
730
733
|
const command = getDevDependenciesInstallationCommand(
|
|
731
734
|
packageManager,
|
|
732
735
|
dependenciesToInstall,
|
|
736
|
+
packageManagerMajorVersion,
|
|
733
737
|
);
|
|
734
738
|
const commandString = command.join(" ");
|
|
735
739
|
|
|
@@ -788,6 +792,7 @@ export async function installProjectDependencies({
|
|
|
788
792
|
const command = getDevDependenciesInstallationCommand(
|
|
789
793
|
packageManager,
|
|
790
794
|
dependenciesToUpdate,
|
|
795
|
+
packageManagerMajorVersion,
|
|
791
796
|
);
|
|
792
797
|
const commandString = command.join(" ");
|
|
793
798
|
|
|
@@ -104,11 +104,16 @@ export function getPackageManager(): PackageManager {
|
|
|
104
104
|
*
|
|
105
105
|
* @param packageManager The package manager to use.
|
|
106
106
|
* @param dependencies The dependencies to install.
|
|
107
|
+
* @param packageManagerMajorVersion The major version of the package manager,
|
|
108
|
+
* if known. Used to opt into version-specific flags (e.g. pnpm 11's
|
|
109
|
+
* `--allow-build=esbuild`, required because `tsx` ships `esbuild` whose
|
|
110
|
+
* postinstall script is otherwise blocked).
|
|
107
111
|
* @returns The installation command.
|
|
108
112
|
*/
|
|
109
113
|
export function getDevDependenciesInstallationCommand(
|
|
110
114
|
packageManager: PackageManager,
|
|
111
115
|
dependencies: string[],
|
|
116
|
+
packageManagerMajorVersion?: number,
|
|
112
117
|
): string[] {
|
|
113
118
|
const packageManagerToCommand: Record<PackageManager, string[]> = {
|
|
114
119
|
npm: ["npm", "install", "--save-dev"],
|
|
@@ -118,6 +123,18 @@ export function getDevDependenciesInstallationCommand(
|
|
|
118
123
|
bun: ["bun", "add", "--dev"],
|
|
119
124
|
};
|
|
120
125
|
const command = packageManagerToCommand[packageManager];
|
|
126
|
+
|
|
127
|
+
// NOTE: adding an unnecessary flag doesn't result in an error
|
|
128
|
+
// nor warning, so we don't check if hardhat or tsx are being
|
|
129
|
+
// installed.
|
|
130
|
+
if (
|
|
131
|
+
packageManager === "pnpm" &&
|
|
132
|
+
packageManagerMajorVersion !== undefined &&
|
|
133
|
+
packageManagerMajorVersion >= 11
|
|
134
|
+
) {
|
|
135
|
+
command.push("--allow-build=esbuild");
|
|
136
|
+
}
|
|
137
|
+
|
|
121
138
|
// We quote all the dependency identifiers so that they can be run on a shell
|
|
122
139
|
// without semver symbols interfering with the command
|
|
123
140
|
command.push(
|
|
@@ -205,7 +222,7 @@ export async function installsPeerDependenciesByDefault(
|
|
|
205
222
|
}
|
|
206
223
|
}
|
|
207
224
|
|
|
208
|
-
async function getVersion(
|
|
225
|
+
export async function getVersion(
|
|
209
226
|
workspace: string,
|
|
210
227
|
packageManager: PackageManager,
|
|
211
228
|
version?: string,
|
package/src/internal/cli/main.ts
CHANGED
|
@@ -318,7 +318,7 @@ export async function main(
|
|
|
318
318
|
}
|
|
319
319
|
} catch (error) {
|
|
320
320
|
ensureError(error);
|
|
321
|
-
printErrorMessages(error, builtinGlobalOptions?.showStackTraces);
|
|
321
|
+
await printErrorMessages(error, builtinGlobalOptions?.showStackTraces);
|
|
322
322
|
|
|
323
323
|
try {
|
|
324
324
|
await sendErrorTelemetry(error);
|
|
@@ -70,7 +70,8 @@ import {
|
|
|
70
70
|
* @param error The error to classify.
|
|
71
71
|
* @param ignoreDevelopmentTimeFilter If true, the classifier will ignore the
|
|
72
72
|
* development-time filter, which is used to exclude errors that happen during
|
|
73
|
-
* development of Hardhat itself.
|
|
73
|
+
* development of Hardhat itself. Set this from display-side callers (where the
|
|
74
|
+
* dev-time skip is irrelevant) and from tests.
|
|
74
75
|
* @returns The error category.
|
|
75
76
|
*/
|
|
76
77
|
export function classifyError(
|
|
@@ -13,21 +13,18 @@ export class UsingHardhat2PluginError extends CustomError {
|
|
|
13
13
|
if (callerPath !== undefined) {
|
|
14
14
|
message = `You are trying to use a Hardhat 2 plugin in a Hardhat 3 project.
|
|
15
15
|
|
|
16
|
-
This file is part of a Hardhat 2 plugin calling an API that was removed in Hardhat 3: ${styleText("bold", callerPath)}
|
|
17
|
-
|
|
18
|
-
Please read https://hardhat.org/migrate-from-hardhat2 to learn how to migrate your project to Hardhat 3.
|
|
19
|
-
`;
|
|
16
|
+
This file is part of a Hardhat 2 plugin calling an API that was removed in Hardhat 3: ${styleText("bold", callerPath)}`;
|
|
20
17
|
} else {
|
|
21
|
-
message = `You are trying to use a Hardhat 2 plugin in a Hardhat 3 project
|
|
22
|
-
|
|
23
|
-
Check the stack trace below to identify which plugin is causing this.
|
|
24
|
-
|
|
25
|
-
Please read https://hardhat.org/migrate-from-hardhat2 to learn how to migrate your project to Hardhat 3.
|
|
26
|
-
`;
|
|
18
|
+
message = `You are trying to use a Hardhat 2 plugin in a Hardhat 3 project.`;
|
|
27
19
|
}
|
|
28
20
|
|
|
29
21
|
super(message);
|
|
30
|
-
|
|
22
|
+
// Use a non-enumerable property so that `console.error(error)` does not
|
|
23
|
+
// print `{ callerRelativePath: '…' }` after the stack trace.
|
|
24
|
+
Object.defineProperty(this, "callerRelativePath", {
|
|
25
|
+
value: callerPath,
|
|
26
|
+
enumerable: false,
|
|
27
|
+
});
|
|
31
28
|
}
|
|
32
29
|
}
|
|
33
30
|
|