Skip to content

Warn on unrecognized config keys with a "did you mean" suggestion#3966

Open
markselby9 wants to merge 1 commit into
facebook:mainfrom
markselby9:feat/3943-config-unknown-keys
Open

Warn on unrecognized config keys with a "did you mean" suggestion#3966
markselby9 wants to merge 1 commit into
facebook:mainfrom
markselby9:feat/3943-config-unknown-keys

Conversation

@markselby9

Copy link
Copy Markdown
Contributor

Summary

Closes #3943.

When a pyrefly.toml / [tool.pyrefly] contains a key Pyrefly doesn't recognize, serde's #[serde(flatten)] catch-all silently swept it into extras, and from_file surfaced it only as a single lumped line:

Extra keys found in config: check-unannotated-def, made-up-key

That tells you something is wrong but not what you meant. This PR replaces it with one warning per unrecognized key and a "did you mean" suggestion when a known option is close:

Unknown config key `check-unannotated-def`. Did you mean `check-unannotated-defs`?
Unknown config key `made-up-key`

(As the issue notes, unknown error kinds already fail to parse — this brings unknown config keys closer to that behavior, while still only warning so users can intentionally share a config across tools.)

Details

  • Scoped candidates. Top-level keys are matched against the project-wide options plus ConfigBase settings; [[sub-config]] keys are matched against matches + ConfigBase only — so a sub-config typo never suggests a project-only key like project-includes.
  • Shared ranking. The suggestion reuses the edit-distance ranking already used for identifier typos in pyrefly_util::suggest. I generalized that module's internals into one private closest<T> and exposed a best_suggestion_str for plain strings; best_suggestion (used by 6 call sites) now delegates to it with unchanged behavior.
  • Migration aliases (e.g. snake_case python_version) are accepted by serde, so they never reach extras and are never flagged.

Test plan

  • New tests in crates/pyrefly_config/src/config.rs:
    • unknown key with a close match → warns + suggests
    • unknown key with no close match → warns, no suggestion
    • unknown key inside a [[sub-config]] → warns with the sub-config context + suggestion
    • canonical keys and a snake_case migration alias → no warnings
    • test_known_config_keys_cover_serialized_fields: a sync guard so newly-added (serialized) config fields must be added to the candidate lists
  • cargo test -p pyrefly_config — 224 passed.
  • cargo test -p pyrefly_util — 71 passed (guards the shared helper refactor).
  • Suggestion-exercising modules in the main crate unaffected: test::attributes (187), test::typed_dict (161), test::scope (96), test::enums (61), test::calls (47) — all green.
  • python3 test.py --no-test --no-tensor-shapes --no-conformance --no-jsonschema — clean.
A config key Pyrefly doesn't recognize — a typo like `check-unannotated-def`,
or a key copied from another tool — is swept into serde's `flatten` catch-all
and was surfaced only as a single lumped "Extra keys found" line, giving no
hint about what the user likely meant.

Emit one warning per unrecognized key and, when a known option is within a
small edit distance, suggest it (e.g. "Did you mean `check-unannotated-defs`?").
Top-level and `[[sub-config]]` keys are matched against the options valid in
their own scope, so a sub-config typo never suggests a project-only key.

The suggestion reuses the edit-distance ranking already used for identifier
typos in `pyrefly_util::suggest`, generalized to plain strings so the config
and identifier paths share one implementation.

Closes facebook#3943
@markselby9 markselby9 force-pushed the feat/3943-config-unknown-keys branch from c1e7715 to a94469b Compare June 29, 2026 04:10
@github-actions github-actions Bot added size/l and removed size/l labels Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

1 participant