Skip to content

Commit 42a88da

Browse files
committed
fix(webpack-cli): address review feedback on lazy option registration
- Register every letter of a combined short token (e.g. `-abc`), not just the first, so clustered boolean short flags are not dropped and reported as unknown options. - Include the `--no-<name>` negated forms in the stashed option-name list so "did you mean" suggestions still work for mistyped negated flags. - Fall back to per-candidate `access` probing when a directory can't be listed (e.g. execute-only permissions), so default-config discovery keeps working in restricted-permission directories. https://claude.ai/code/session_01PEtzv6Xqv2yXQaQsZaeoSF
1 parent 50a9e7c commit 42a88da

1 file changed

Lines changed: 39 additions & 14 deletions

File tree

packages/webpack-cli/src/webpack-cli.ts

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -654,11 +654,20 @@ class WebpackCLI {
654654
commandOptions = options.options;
655655
}
656656

657-
// Keep all option names for "did you mean" suggestions on unknown options,
658-
// since not every option is registered on commander below.
659-
(command as Command & { allOptionNames?: string[] }).allOptionNames = commandOptions.map(
660-
(option) => option.name,
661-
);
657+
// Keep all option names (including the `no-` negated forms commander
658+
// registers) for "did you mean" suggestions on unknown options, since not
659+
// every option is registered on commander below.
660+
const allOptionNames: string[] = [];
661+
662+
for (const option of commandOptions) {
663+
allOptionNames.push(option.name);
664+
665+
if (this.#optionSupportsNegation(option)) {
666+
allOptionNames.push(`no-${option.name}`);
667+
}
668+
}
669+
670+
(command as Command & { allOptionNames?: string[] }).allOptionNames = allOptionNames;
662671

663672
// For help we register every option (help lists them all). Otherwise we
664673
// register only the options actually present in argv, avoiding the cost of
@@ -714,9 +723,13 @@ class WebpackCLI {
714723
names.add(name.slice(3));
715724
}
716725
} else {
717-
// Short option: the alias is the first character; the rest (if any) is
718-
// an attached value, e.g. `-d<value>` means `-d <value>`.
719-
names.add(token[1]);
726+
// Short option(s): either a single option with an attached value
727+
// (`-d<value>`) or combined boolean flags (`-abc` => `-a -b -c`). Since
728+
// we can't tell which without the option definitions, register every
729+
// letter; over-registering an unused option is harmless.
730+
for (const char of token.slice(1).split("=", 1)[0]) {
731+
names.add(char);
732+
}
720733
}
721734
}
722735

@@ -734,6 +747,19 @@ class WebpackCLI {
734747
return typeof alias === "string" && neededOptions.has(alias);
735748
}
736749

750+
// Mirrors when `makeOption` registers a `--no-<name>` negated option.
751+
#optionSupportsNegation(option: CommandOption): boolean {
752+
if (option.configs) {
753+
return option.configs.some(
754+
(config) =>
755+
config.type === "boolean" ||
756+
(config.type === "enum" && (config.values || []).includes(false)),
757+
);
758+
}
759+
760+
return Boolean(option.negative);
761+
}
762+
737763
makeOption(command: Command, option: CommandOption) {
738764
type MainOption = Pick<
739765
CommandOption,
@@ -2492,15 +2518,14 @@ class WebpackCLI {
24922518
configFileSearch: for (const filename of DEFAULT_CONFIGURATION_FILES) {
24932519
const resolvedBase = path.resolve(filename);
24942520
const entries = await readDirectoryEntries(path.dirname(resolvedBase));
2495-
2496-
if (!entries) {
2497-
continue;
2498-
}
2499-
25002521
const basename = path.basename(resolvedBase);
25012522

25022523
for (const ext of orderedExtensions) {
2503-
if (!entries.has((basename + ext).toLowerCase())) {
2524+
// Fast path: skip candidates absent from the directory listing. When
2525+
// the directory can't be listed (e.g. execute-only permissions),
2526+
// `entries` is `null`, so probe every candidate directly with `access`
2527+
// to keep discovery working in restricted-permission directories.
2528+
if (entries && !entries.has((basename + ext).toLowerCase())) {
25042529
continue;
25052530
}
25062531

0 commit comments

Comments
 (0)