Linters run on one package at a time rather than one target at a
time. This is mostly because they need to run outside the context of
apps in various places (eg when you publish the package, though that's
currently unimplemented).
This is in addition to registering for extensions. Note that only the
new SourceProcessor APIs allow this, not registerSourceHandler.
The filename in question is the basename of the file. The file can be
found in any directory in any package. If you want to be more picky,
you can just ignore other ones in your processFilesForTarget.
This introduces the SourceProcessorSet abstraction, which simplifies a
lot of repeated code around matching filenames with processors and
avoiding duplicates.
Missing tests.
See also #3985.