Skip to content

User include/exclude lists are index-merged with the defaults, not replaced #48

Description

@FluffyDiscord

Config::get() merges the user's typephp.php over the defaults with
array_replace_recursive() (src/Internal/Config.php:212), which merges lists by index. A
user config therefore cannot replace include/exclude; it only overwrites the first N entries.

Repro (v0.6.0) — typephp.php:

return ['include' => ['src/**'], 'exclude' => ['vendor/**', 'tests/**', 'var/**']];
require 'vendor/autoload.php';
var_export(TypePHP\Internal\Config::get()['include']);
// ['src/**', 'app/**', 'internals/**', 'tests/**']   <- app/**, internals/**, tests/** leaked in
var_export(TypePHP\Internal\Config::get()['exclude']);
// ['vendor/**', 'tests/**', 'var/**', 'cache/**']    <- storage/** silently dropped

tests/** then sits in both lists, and whether files under it are transformed comes down to
PathMatcher::isPathIncluded()'s $longestIncludeMatch > $longestExcludeMatch tie-break on equal
glob lengths (8 > 8 is false). Lengthening either glob flips the behaviour.

Impact. include/exclude do not mean what the config file says. Excluding a directory can
depend on the character count of the pattern used.

Suggested fix. Replace include, exclude, extensions and stubs wholesale when the user
config declares them, rather than recursively merging the lists.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions