Skip to content
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

Updates to RESERVED_PARAMETER_NAMES and GLOBAL_OPTIONS #5470

Merged
merged 6 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions v-next/core/src/internal/parameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,10 @@ import { HardhatError } from "@ignored/hardhat-vnext-errors";
import { ParameterType } from "../types/common.js";

/**
* Names that can't be used as global- nor task-parameter names.
* Names that can't be used as global- nor task-parameter names. These are
* reserved for future use.
*/
export const RESERVED_PARAMETER_NAMES: Set<string> = new Set([
"config",
"help",
"showStackTraces",
"version",
]);
export const RESERVED_PARAMETER_NAMES: Set<string> = new Set([]);

const VALID_PARAM_NAME_CASING_REGEX = /^[a-z][a-zA-Z0-9]*$/;

Expand Down
16 changes: 15 additions & 1 deletion v-next/core/test/internal/global-options.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { after, before, describe, it } from "node:test";

import { HardhatError } from "@ignored/hardhat-vnext-errors";

Expand All @@ -13,6 +13,20 @@ import { RESERVED_PARAMETER_NAMES } from "../../src/internal/parameters.js";
import { createTestEnvManager } from "../utils.js";

describe("Global Options", () => {
before(() => {
// Make sure we have some reserved names
RESERVED_PARAMETER_NAMES.add("testName1");
RESERVED_PARAMETER_NAMES.add("testName2");
RESERVED_PARAMETER_NAMES.add("testName3");
});

after(() => {
// Delete the test reserved names
RESERVED_PARAMETER_NAMES.delete("testName1");
RESERVED_PARAMETER_NAMES.delete("testName2");
RESERVED_PARAMETER_NAMES.delete("testName3");
});

describe("buildGlobalOptionsMap", () => {
it("should build an empty map of global options if no plugins are provided", () => {
const globalOptionsMap = buildGlobalOptionsMap([]);
Expand Down
16 changes: 15 additions & 1 deletion v-next/core/test/internal/tasks/builders.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { after, before, describe, it } from "node:test";

import { HardhatError } from "@ignored/hardhat-vnext-errors";

Expand All @@ -13,6 +13,20 @@ import { ParameterType } from "../../../src/types/common.js";
import { TaskDefinitionType } from "../../../src/types/tasks.js";

describe("Task builders", () => {
before(() => {
// Make sure we have some reserved names
RESERVED_PARAMETER_NAMES.add("testName1");
RESERVED_PARAMETER_NAMES.add("testName2");
RESERVED_PARAMETER_NAMES.add("testName3");
});

after(() => {
// Delete the test reserved names
RESERVED_PARAMETER_NAMES.delete("testName1");
RESERVED_PARAMETER_NAMES.delete("testName2");
RESERVED_PARAMETER_NAMES.delete("testName3");
});

describe("EmptyTaskDefinitionBuilderImplementation", () => {
it("should create an empty task definition builder", () => {
const builder = new EmptyTaskDefinitionBuilderImplementation("task-id");
Expand Down
8 changes: 8 additions & 0 deletions v-next/example-project/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
emptyTask,
overrideTask,
configVariable,
globalOption,
} from "@ignored/hardhat-vnext/config";

const exampleEmptyTask = emptyTask("empty", "An example empty task").build();
Expand Down Expand Up @@ -116,6 +117,13 @@ const pluginExample = {
})
.build(),
],
globalOptions: [
globalOption({
name: "myGlobalOption",
description: "A global option",
defaultValue: "default",
}),
],
};

const config: HardhatUserConfig = {
Expand Down
31 changes: 31 additions & 0 deletions v-next/hardhat/src/internal/builtin-options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { GlobalOption } from "../types/global-options.js";

import { globalOption, ParameterType } from "../config.js";

export const BUILTIN_OPTIONS: GlobalOption[] = [
globalOption({
name: "config",
description: "A Hardhat config file.",
parameterType: ParameterType.STRING,
defaultValue: "",
}),
globalOption({
name: "help",
description:
"Shows this message, or a task's help if its name is provided.",
parameterType: ParameterType.BOOLEAN,
defaultValue: false,
}),
globalOption({
name: "showStackTraces",
description: "Show stack traces (always enabled on CI servers).",
parameterType: ParameterType.BOOLEAN,
defaultValue: false,
}),
globalOption({
name: "version",
description: "Shows hardhat's version.",
parameterType: ParameterType.BOOLEAN,
defaultValue: false,
}),
];
10 changes: 7 additions & 3 deletions v-next/hardhat/src/internal/cli/helpers/getGlobalHelpString.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import type { GlobalOptionsMap } from "@ignored/hardhat-vnext-core/types/global-options";
import type { Task } from "@ignored/hardhat-vnext-core/types/tasks";

import { getHardhatVersion } from "../../utils/package.js";

import {
GLOBAL_NAME_PADDING,
GLOBAL_OPTIONS,
getLongestNameLength,
getSection,
parseGlobalOptions,
parseTasks,
} from "./utils.js";

export async function getGlobalHelpString(
rootTasks: Map<string, Task>,
globalOptionsMap: GlobalOptionsMap,
): Promise<string> {
const version = await getHardhatVersion();

const { tasks, subtasks } = parseTasks(rootTasks);

const globalOptions = parseGlobalOptions(globalOptionsMap);

const namePadding =
getLongestNameLength([...tasks, ...subtasks, ...GLOBAL_OPTIONS]) +
getLongestNameLength([...tasks, ...subtasks, ...globalOptions]) +
GLOBAL_NAME_PADDING;

let output = `Hardhat version ${version}
Expand All @@ -34,7 +38,7 @@ Usage: hardhat [GLOBAL OPTIONS] <TASK> [SUBTASK] [TASK OPTIONS] [--] [TASK ARGUM
output += getSection("AVAILABLE SUBTASKS", subtasks, namePadding);
}

output += getSection("GLOBAL OPTIONS", GLOBAL_OPTIONS, namePadding);
output += getSection("GLOBAL OPTIONS", globalOptions, namePadding);

output += `\nTo get help for a specific task run: npx hardhat <TASK> [SUBTASK] --help`;

Expand Down
68 changes: 35 additions & 33 deletions v-next/hardhat/src/internal/cli/helpers/utils.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,41 @@
import type { ParameterType } from "@ignored/hardhat-vnext-core/config";
import type { GlobalOptionsMap } from "@ignored/hardhat-vnext-core/types/global-options";
import type { Task } from "@ignored/hardhat-vnext-core/types/tasks";

export const GLOBAL_OPTIONS: Array<{
import { BUILTIN_OPTIONS } from "../../builtin-options.js";

export const GLOBAL_NAME_PADDING = 6;

interface ArgumentDescriptor {
name: string;
description: string;
}> = [
{
name: "--config",
description: "A Hardhat config file.",
},
{
name: "--help",
description: "Shows this message, or a task's help if its name is provided",
},
{
name: "--show-stack-traces",
description: "Show stack traces (always enabled on CI servers).",
},
{
name: "--version",
description: "Shows hardhat's version.",
},
];
type?: ParameterType;
isRequired?: boolean;
}

export const GLOBAL_NAME_PADDING = 6;
export function parseGlobalOptions(
globalOptionsMap: GlobalOptionsMap,
): ArgumentDescriptor[] {
const formattedBuiltinOptions = BUILTIN_OPTIONS.map(
({ name, description }) => ({
name: formatOptionName(name),
description,
}),
);

const formattedUserOptions = Array.from(globalOptionsMap).map(([, entry]) => {
return {
name: formatOptionName(entry.option.name),
description: entry.option.description,
};
});

return [...formattedBuiltinOptions, ...formattedUserOptions];
}

export function parseTasks(taskMap: Map<string, Task>): {
tasks: Array<{ name: string; description: string }>;
subtasks: Array<{ name: string; description: string }>;
tasks: ArgumentDescriptor[];
subtasks: ArgumentDescriptor[];
} {
const tasks = [];
const subtasks = [];
Expand All @@ -45,9 +53,7 @@ export function parseTasks(taskMap: Map<string, Task>): {
return { tasks, subtasks };
}

export function parseSubtasks(
task: Task,
): Array<{ name: string; description: string }> {
export function parseSubtasks(task: Task): ArgumentDescriptor[] {
const subtasks = [];

for (const [, subtask] of task.subtasks) {
Expand All @@ -61,12 +67,8 @@ export function parseSubtasks(
}

export function parseOptions(task: Task): {
options: Array<{ name: string; description: string; type: ParameterType }>;
positionalArguments: Array<{
name: string;
description: string;
isRequired: boolean;
}>;
options: ArgumentDescriptor[];
positionalArguments: ArgumentDescriptor[];
} {
const options = [];
const positionalArguments = [];
Expand Down Expand Up @@ -107,7 +109,7 @@ export function getLongestNameLength(tasks: Array<{ name: string }>): number {

export function getSection(
title: string,
items: Array<{ name: string; description: string }>,
items: ArgumentDescriptor[],
namePadding: number,
): string {
return `\n${title}:\n\n${items.map(({ name, description }) => ` ${name.padEnd(namePadding)}${description}`).join("\n")}\n`;
Expand All @@ -125,7 +127,7 @@ export function getUsageString(
}

if (positionalArguments.length > 0) {
output += ` [--] ${positionalArguments.map((a) => (a.isRequired ? a.name : `[${a.name}]`)).join(" ")}`;
output += ` [--] ${positionalArguments.map((a) => (a.isRequired === true ? a.name : `[${a.name}]`)).join(" ")}`;
}

return output;
Expand Down
5 changes: 4 additions & 1 deletion v-next/hardhat/src/internal/cli/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ export async function main(

if (Array.isArray(taskOrId)) {
if (taskOrId.length === 0) {
const globalHelp = await getGlobalHelpString(hre.tasks.rootTasks);
const globalHelp = await getGlobalHelpString(
hre.tasks.rootTasks,
globalOptionsMap,
);

print(globalHelp);
return;
Expand Down
60 changes: 54 additions & 6 deletions v-next/hardhat/test/internal/cli/helpers/getGlobalHelpString.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import type { Task } from "@ignored/hardhat-vnext-core/types/tasks";
import assert from "node:assert/strict";
import { describe, it } from "node:test";

import { buildGlobalOptionsMap } from "@ignored/hardhat-vnext-core";
import {
globalOption,
ParameterType,
} from "@ignored/hardhat-vnext-core/config";
import { readClosestPackageJson } from "@ignored/hardhat-vnext-utils/package";

import { getGlobalHelpString } from "../../../../src/internal/cli/helpers/getGlobalHelpString.js";
Expand All @@ -13,7 +18,7 @@ describe("getGlobalHelpString", async function () {
describe("when there are no tasks", function () {
it("should return the global help string", async function () {
const tasks = new Map();
const help = await getGlobalHelpString(tasks);
const help = await getGlobalHelpString(tasks, new Map());

const expected = `Hardhat version ${packageJson.version}

Expand All @@ -22,7 +27,7 @@ Usage: hardhat [GLOBAL OPTIONS] <TASK> [SUBTASK] [TASK OPTIONS] [--] [TASK ARGUM
GLOBAL OPTIONS:

--config A Hardhat config file.
--help Shows this message, or a task's help if its name is provided
--help Shows this message, or a task's help if its name is provided.
--show-stack-traces Show stack traces (always enabled on CI servers).
--version Shows hardhat's version.

Expand Down Expand Up @@ -65,7 +70,7 @@ To get help for a specific task run: npx hardhat <TASK> [SUBTASK] --help`;
],
]);

const help = await getGlobalHelpString(tasks);
const help = await getGlobalHelpString(tasks, new Map());

const expected = `Hardhat version ${packageJson.version}

Expand All @@ -79,7 +84,7 @@ AVAILABLE TASKS:
GLOBAL OPTIONS:

--config A Hardhat config file.
--help Shows this message, or a task's help if its name is provided
--help Shows this message, or a task's help if its name is provided.
--show-stack-traces Show stack traces (always enabled on CI servers).
--version Shows hardhat's version.

Expand Down Expand Up @@ -132,7 +137,7 @@ To get help for a specific task run: npx hardhat <TASK> [SUBTASK] --help`;
],
]);

const help = await getGlobalHelpString(tasks);
const help = await getGlobalHelpString(tasks, new Map());

const expected = `Hardhat version ${packageJson.version}

Expand All @@ -150,10 +155,53 @@ AVAILABLE SUBTASKS:
GLOBAL OPTIONS:

--config A Hardhat config file.
--help Shows this message, or a task's help if its name is provided
--help Shows this message, or a task's help if its name is provided.
--show-stack-traces Show stack traces (always enabled on CI servers).
--version Shows hardhat's version.

To get help for a specific task run: npx hardhat <TASK> [SUBTASK] --help`;

assert.equal(help, expected);
});
});

describe("when there are user-defined global options", function () {
it("should return the global help string with the user-defined global options", async function () {
const tasks = new Map();
const globalOptionsMap = buildGlobalOptionsMap([
{
id: "plugin1",
globalOptions: [
globalOption({
name: "userOption1",
description: "userOption1 description.",
parameterType: ParameterType.STRING,
defaultValue: "default",
}),
globalOption({
name: "userOption2",
description: "userOption2 description.",
parameterType: ParameterType.STRING,
defaultValue: "default",
}),
],
},
]);
const help = await getGlobalHelpString(tasks, globalOptionsMap);

const expected = `Hardhat version ${packageJson.version}

Usage: hardhat [GLOBAL OPTIONS] <TASK> [SUBTASK] [TASK OPTIONS] [--] [TASK ARGUMENTS]

GLOBAL OPTIONS:

--config A Hardhat config file.
--help Shows this message, or a task's help if its name is provided.
--show-stack-traces Show stack traces (always enabled on CI servers).
--version Shows hardhat's version.
--user-option-1 userOption1 description.
--user-option-2 userOption2 description.

To get help for a specific task run: npx hardhat <TASK> [SUBTASK] --help`;

assert.equal(help, expected);
Expand Down
Loading