prefer_match_file_name
Flags a file whose name does not match the first public declaration in it: user_repository.dart should declare class UserRepository.
The SDK’s file_names rule validates the spelling of a file name but never checks whether it describes the contents. Matching them is what lets a reader find a type from a directory listing, and what makes renaming a type show up in review as a rename of its file rather than as an unrelated edit buried in a diff.
This rule is in the pedantic preset. It works out of the box; enable it in any other preset by name:
rules: prefer_match_file_name: enabled: trueSee also: file_names, Effective Dart: naming
// In a file named repo.dart:class UserRepository {}// In a file named user_repository.dart:class UserRepository {}Examples
Section titled “Examples”Only the first public declaration is checked
Section titled “Only the first public declaration is checked”A file legitimately holds several — a class plus its extension, a sealed hierarchy — and only one of them can name the file, so the rest are not evidence of a problem:
// user_repository.dart — acceptedclass UserRepository {}
// Not reported: the first public declaration already named the file.extension UserRepositoryCaching on UserRepository {}
class UserRepositoryException implements Exception {}Private declarations are skipped over
Section titled “Private declarations are skipped over”The scan looks for the first public declaration, so a private helper at the top does not become the file’s name:
// user_repository.dart — acceptedclass _CacheEntry {}
class UserRepository {}Acronyms convert the way a reader expects
Section titled “Acronyms convert the way a reader expects”HTTPClient maps to http_client.dart, not h_t_t_p_client.dart:
// http_client.dart — acceptedclass HTTPClient {}// api_v2_gateway.dart — acceptedclass APIV2Gateway {}Entrypoint functions are skipped, not reported
Section titled “Entrypoint functions are skipped, not reported”main, onRequest and middleware are names the language or a framework demands, which therefore cannot name the file. They are skipped and the scan moves to the next declaration:
// user_repository_test.dart — accepted; `main` is skipped, and there is// no other public declaration to name the file.void main() { // ...}Add your own with additional_entrypoints, which extends the defaults instead of replacing them:
many_lints: rules: prefer_match_file_name: additional_entrypoints: [buildTransaction]rules: prefer_match_file_name: additional_entrypoints: [buildTransaction]Skipping generated files
Section titled “Skipping generated files”many_lints: rules: prefer_match_file_name: ignored_suffixes: ['.g.dart', '.freezed.dart']rules: prefer_match_file_name: ignored_suffixes: ['.g.dart', '.freezed.dart']Generated files are usually better handled with the global analyzer: exclude:, which stops them being analyzed at all. Reach for ignored_suffixes when you still want other rules to see them.
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
ignored_suffixes |
list of strings | [] |
File-name suffixes the rule skips entirely, matched with the extension included |
entrypoints |
list of strings | [main, onRequest, middleware] |
Function names a framework demands, which never name a file. Setting this replaces the defaults |
additional_entrypoints |
list of strings | [] |
Entrypoints to add to the defaults, instead of restating them |
Known limitations
Section titled “Known limitations”A part file is never reported. Its name belongs to the composite it is part of (_header.dart inside profile_page/) rather than to its own declaration.
A file with no public declaration is never reported. A private-only file has no name to match, and a barrel of export directives declares nothing at all.
An anonymous extension cannot name a file, so it is skipped and the scan continues to the next declaration.
Only top-level declarations count. A class nested in nothing but a public variable or a top-level const is not a declaration this rule reads — fields and variables are not scanned.
No quick fix. Fixing this means renaming either the file or the declaration, and which one is right is the question the diagnostic is asking.
Turning this rule off
Section titled “Turning this rule off”To disable this rule:
rules: prefer_match_file_name: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Related rules
Section titled “Related rules”prefer_single_declaration_per_file— Keep one top-level declaration per file, with per-type budgets.match_lib_folder_structure— Keep folders under lib/ in lower_snake_case.prefer_single_widget_per_file— Keep one public widget per file for better organization.prefer_correct_test_file_name— Name test files so the runner actually runs them.