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

Consolidate argument naming #5484

Merged
merged 12 commits into from
Jul 4, 2024
2 changes: 1 addition & 1 deletion v-next/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
"exports": {
".": "./dist/src/index.js",
"./config": "./dist/src/config.js",
"./types/arguments": "./dist/src/types/arguments.js",
"./types/cli": "./dist/src/types/cli.js",
"./types/common": "./dist/src/types/common.js",
"./types/config": "./dist/src/types/config.js",
"./types/global-options": "./dist/src/types/global-options.js",
"./types/hooks": "./dist/src/types/hooks.js",
Expand Down
4 changes: 2 additions & 2 deletions v-next/core/scripts/api-extractor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ export type * from "./index.js";
export * from "./config.js";
export type * from "./config.js";

export * from "./types/arguments.js";
export type * from "./types/arguments.js";
export * from "./types/cli.js";
export type * from "./types/cli.js";
export * from "./types/common.js";
export type * from "./types/common.js";
export * from "./types/config.js";
export type * from "./types/config.js";
export * from "./types/global-options.js";
Expand Down
18 changes: 9 additions & 9 deletions v-next/core/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ParameterTypeToValueType } from "./types/common.js";
import type { ArgumentTypeToValueType } from "./types/arguments.js";
import type { ConfigurationVariable } from "./types/config.js";
import type { GlobalOption } from "./types/global-options.js";
import type { GlobalOptionDefinition } from "./types/global-options.js";
import type {
EmptyTaskDefinitionBuilder,
NewTaskDefinitionBuilder,
Expand All @@ -13,11 +13,11 @@ import {
NewTaskDefinitionBuilderImplementation,
TaskOverrideDefinitionBuilderImplementation,
} from "./internal/tasks/builders.js";
import { ParameterType } from "./types/common.js";
import { ArgumentType } from "./types/arguments.js";

export type { HardhatUserConfig } from "./types/config.js";

export { ParameterType } from "./types/common.js";
export { ArgumentType } from "./types/arguments.js";

/**
* Creates a configuration variable, which will be fetched at runtime.
Expand Down Expand Up @@ -58,12 +58,12 @@ export function overrideTask(
/**
* Defines a global option.
*/
export function globalOption<T extends ParameterType>(options: {
export function globalOption<T extends ArgumentType>(options: {
name: string;
description: string;
type?: T;
defaultValue: ParameterTypeToValueType<T>;
}): GlobalOption {
defaultValue: ArgumentTypeToValueType<T>;
}): GlobalOptionDefinition {
return buildGlobalOptionDefinition(options);
}

Expand All @@ -73,10 +73,10 @@ export function globalOption<T extends ParameterType>(options: {
export function globalFlag(options: {
name: string;
description: string;
}): GlobalOption {
}): GlobalOptionDefinition {
return buildGlobalOptionDefinition({
...options,
type: ParameterType.BOOLEAN,
type: ArgumentType.BOOLEAN,
defaultValue: false,
});
}
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
import type { ParameterValue } from "../types/common.js";
import type { ArgumentValue } from "../types/arguments.js";

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

import { ParameterType } from "../types/common.js";
import { ArgumentType } from "../types/arguments.js";

/**
* Names that can't be used as global- nor task-parameter names. These are
* reserved for future use.
* Names that cannot be used for global or task arguments.
* Reserved for future use.
*/
export const RESERVED_PARAMETER_NAMES: Set<string> = new Set([]);
export const RESERVED_ARGUMENT_NAMES: Set<string> = new Set([]);

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

/**
* Returns true if the given name is a valid parameter name.
* Returns true if the given name is a valid argument name.
*/
export function isValidParamNameCasing(name: string): boolean {
return VALID_PARAM_NAME_CASING_REGEX.test(name);
export function isArgumentNameValid(name: string): boolean {
return VALID_ARGUMENT_NAME_PATTERN.test(name);
}

/**
* Checks if a parameter value is valid for a given parameter type.
* Checks if an argument value is valid for a given argument type.
*
* This function uses a map of validators, where each validator is a function
* that checks if a value is valid for a specific parameter type.
* If the parameter type is variadic, the value is considered valid if it is an
* array and all its elements are valid for the parameter type. An empty array
* that checks if a value is valid for a specific argument type.
* If the argument type is variadic, the value is considered valid if it is an
* array and all its elements are valid for the argument type. An empty array
* is considered invalid.
*/
export function isParameterValueValid(
type: ParameterType,
export function isArgumentValueValid(
type: ArgumentType,
value: unknown,
isVariadic: boolean = false,
): boolean {
const validator = parameterTypeValidators[type];
const validator = argumentTypeValidators[type];

if (isVariadic) {
return Array.isArray(value) && value.length > 0 && value.every(validator);
Expand All @@ -42,40 +42,40 @@ export function isParameterValueValid(
return validator(value);
}

const parameterTypeValidators: Record<
ParameterType,
const argumentTypeValidators: Record<
ArgumentType,
(value: unknown) => boolean
> = {
[ParameterType.STRING]: (value): value is string => typeof value === "string",
[ParameterType.BOOLEAN]: (value): value is boolean =>
[ArgumentType.STRING]: (value): value is string => typeof value === "string",
[ArgumentType.BOOLEAN]: (value): value is boolean =>
typeof value === "boolean",
[ParameterType.INT]: (value): value is number => Number.isInteger(value),
[ParameterType.BIGINT]: (value): value is bigint => typeof value === "bigint",
[ParameterType.FLOAT]: (value): value is number => typeof value === "number",
[ParameterType.FILE]: (value): value is string => typeof value === "string",
[ArgumentType.INT]: (value): value is number => Number.isInteger(value),
[ArgumentType.BIGINT]: (value): value is bigint => typeof value === "bigint",
[ArgumentType.FLOAT]: (value): value is number => typeof value === "number",
[ArgumentType.FILE]: (value): value is string => typeof value === "string",
};

/**
* Parses a parameter value from a string to the corresponding type.
* Parses an argument value from a string to the corresponding type.
*/
// TODO: this code is duplicated in v-next/hardhat/src/internal/cli/main.ts
// we should move it to a shared place and add tests
export function parseParameterValue(
export function parseArgumentValue(
value: string,
type: ParameterType,
type: ArgumentType,
name: string,
): ParameterValue {
): ArgumentValue {
switch (type) {
case ParameterType.STRING:
case ParameterType.FILE:
case ArgumentType.STRING:
case ArgumentType.FILE:
return value;
case ParameterType.INT:
case ArgumentType.INT:
return validateAndParseInt(name, value);
case ParameterType.FLOAT:
case ArgumentType.FLOAT:
return validateAndParseFloat(name, value);
case ParameterType.BIGINT:
case ArgumentType.BIGINT:
return validateAndParseBigInt(name, value);
case ParameterType.BOOLEAN:
case ArgumentType.BOOLEAN:
return validateAndParseBoolean(name, value);
}
}
Expand All @@ -90,7 +90,7 @@ function validateAndParseInt(name: string, value: string): number {
{
value,
name,
type: ParameterType.INT,
type: ArgumentType.INT,
},
);
}
Expand All @@ -108,7 +108,7 @@ function validateAndParseFloat(name: string, value: string): number {
{
value,
name,
type: ParameterType.FLOAT,
type: ArgumentType.FLOAT,
},
);
}
Expand All @@ -126,7 +126,7 @@ function validateAndParseBigInt(name: string, value: string): bigint {
{
value,
name,
type: ParameterType.BIGINT,
type: ArgumentType.BIGINT,
},
);
}
Expand All @@ -143,7 +143,7 @@ function validateAndParseBoolean(name: string, value: string): boolean {
{
value,
name,
type: ParameterType.BOOLEAN,
type: ArgumentType.BOOLEAN,
},
);
}
Expand Down
42 changes: 21 additions & 21 deletions v-next/core/src/internal/global-options.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import type {
ParameterTypeToValueType,
ParameterValue,
} from "../types/common.js";
ArgumentTypeToValueType,
ArgumentValue,
} from "../types/arguments.js";
import type {
GlobalOptions,
GlobalOption,
GlobalOptionDefinition,
GlobalOptionDefinitions,
} from "../types/global-options.js";
import type { HardhatPlugin } from "../types/plugins.js";

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

import { ParameterType } from "../types/common.js";
import { ArgumentType } from "../types/arguments.js";

import {
RESERVED_PARAMETER_NAMES,
isParameterValueValid,
isValidParamNameCasing,
parseParameterValue,
} from "./parameters.js";
RESERVED_ARGUMENT_NAMES,
isArgumentValueValid,
isArgumentNameValid,
parseArgumentValue,
} from "./arguments.js";

/**
* Builds a map of the global option definitions by going through all the
Expand Down Expand Up @@ -70,7 +70,7 @@ export function buildGlobalOptionDefinitions(
* Builds a global option definition, validating the name, type, and default
* value.
*/
export function buildGlobalOptionDefinition<T extends ParameterType>({
export function buildGlobalOptionDefinition<T extends ArgumentType>({
name,
description,
type,
Expand All @@ -79,23 +79,23 @@ export function buildGlobalOptionDefinition<T extends ParameterType>({
name: string;
description: string;
type?: T;
defaultValue: ParameterTypeToValueType<T>;
}): GlobalOption {
const parameterType = type ?? ParameterType.STRING;
defaultValue: ArgumentTypeToValueType<T>;
}): GlobalOptionDefinition {
const argumentType = type ?? ArgumentType.STRING;

if (!isValidParamNameCasing(name)) {
if (!isArgumentNameValid(name)) {
throw new HardhatError(HardhatError.ERRORS.ARGUMENTS.INVALID_NAME, {
name,
});
}

if (RESERVED_PARAMETER_NAMES.has(name)) {
if (RESERVED_ARGUMENT_NAMES.has(name)) {
throw new HardhatError(HardhatError.ERRORS.ARGUMENTS.RESERVED_NAME, {
name,
});
}

if (!isParameterValueValid(parameterType, defaultValue)) {
if (!isArgumentValueValid(argumentType, defaultValue)) {
throw new HardhatError(
HardhatError.ERRORS.ARGUMENTS.INVALID_VALUE_FOR_TYPE,
{
Expand All @@ -109,7 +109,7 @@ export function buildGlobalOptionDefinition<T extends ParameterType>({
return {
name,
description,
type: parameterType,
type: argumentType,
defaultValue,
};
}
Expand Down Expand Up @@ -146,7 +146,7 @@ export function resolveGlobalOptions(
assign the value. */
(userProvidedGlobalOptions as Record<string, string | undefined>)[name];

let parsedValue: ParameterValue;
let parsedValue: ArgumentValue;
// if the value is provided in the user options, it's already parsed
// and it takes precedence over env vars
if (value !== undefined) {
Expand All @@ -155,7 +155,7 @@ export function resolveGlobalOptions(
value = process.env[`HARDHAT_${camelToSnakeCase(name).toUpperCase()}`];
if (value !== undefined) {
// if the value is provided via an env var, it needs to be parsed
parsedValue = parseParameterValue(value, option.type, name);
parsedValue = parseArgumentValue(value, option.type, name);
} else {
// if the value is not provided by the user or env var, use the default
parsedValue = option.defaultValue;
Expand All @@ -165,7 +165,7 @@ export function resolveGlobalOptions(
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
-- GlobalOptions is empty for user extension, so we need to cast it to
assign the value. */
(globalOptions as Record<string, ParameterValue>)[name] = parsedValue;
(globalOptions as Record<string, ArgumentValue>)[name] = parsedValue;
}

return globalOptions;
Expand Down
Loading