fix: preserve globstar in non-final extglob alternatives#177
Open
DucMinhNe wants to merge 1 commit into
Open
Conversation
In a negation extglob such as `!(a/**|b/**)`, only the last alternative's
`**` compiled to a real globstar; every non-final alternative's `**` was
downgraded to a single path segment (`[^/]*?`). This made negation results
depend on the order of the alternatives — e.g. `!(a/**|b/**)**` and
`!(b/**|a/**)**` matched `a/x/y` differently.
The globstar-downgrade guard in `push` kept a `**` only when the following
token was `tok.type === 'pipe'`, but the `|` token is pushed as
`{ type: 'text', value: '|' }`, so that branch never fired. Also treat a
token whose value is `|` as an extglob boundary.
Fixes micromatch#154
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #154.
Problem
In a negation extglob like
!(a/**|b/**), the result depends on the order of the alternatives:Only the last alternative's
**compiles to a real globstar. Every non-final alternative's**is silently downgraded to a single path segment ([^/]*?), so it can't match deep paths inside the lookahead — and the negation fails to exclude them.Cause
The globstar-downgrade guard in
push(lib/parse.js) keeps a**as a globstar when the following token is a pipe:But the
|token is pushed as{ type: 'text', value: '|' }(see thePipesbranch), nevertype: 'pipe'. Sotok.type === 'pipe'is effectively dead code and the preceding globstar gets downgraded. The last alternative survives only because it is followed by)(type: 'paren', which is guarded) — hence the order-dependence.Fix
Also treat a token whose value is
|as an extglob boundary:This is surgical — it only affects
**immediately followed by|inside an extglob.Tests
Added a regression test in
test/extglobs.jsasserting the negation result is independent of alternative order, that the last alternative still excludes deep paths, and that unrelated paths are still matched (no over-exclusion).Full suite: 1976 passing, lint clean. Verified the new test fails on
masterand passes with the fix.