Skip to content

Commit

Permalink
Remove \G handling case that adds complexity and trades against other…
Browse files Browse the repository at this point in the history
… supported cases
  • Loading branch information
slevithan committed Nov 13, 2024
1 parent 547dfb5 commit 1c8c5b6
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 74 deletions.
54 changes: 1 addition & 53 deletions spec/match-search-start.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,59 +82,7 @@ describe('Assertion: Search start', () => {
expect(() => toDetails(r`(\Ga)+\G`)).toThrow();
});

it('should allow if leading in a leading positive lookahead', () => {
expect('a').toExactlyMatch(r`(?=\G)a`);
expect('a').toExactlyMatch(r`(?=\Ga)a`);
expect('aaba'.match(toRegExp(r`(?=\Ga)a`, {global: true}))).toEqual(['a', 'a']);
expect(['a', 'b']).toExactlyMatch(r`(?=\G)a|\Gb`);
expect('a').toExactlyMatch(r`((?=\G)a)`);
expect(['a', 'A']).toExactlyMatch({
pattern: r`(?i)(?=\G)a`,
maxTestTarget: maxTestTargetForPatternMods,
});
// Similar but not covered
[ r`(?=\G|)a`,
r`(?:(?=\G))?a`,
r`(?=\G)a|b`,
].forEach(pattern => {
expect(() => toDetails(pattern, {avoidSubclass: true})).toThrow();
});
});

it('should allow if trailing in a leading positive lookbehind', () => {
expect('a').toExactlyMatch(r`(?<=\G)a`);
expect(['aa', 'abaa']).not.toFindMatch(r`(?<=a\G)a`);
let re = toRegExp(r`(?<=a\G)a`);
re.lastIndex = 3;
expect(re.exec('abaa')?.index).toBe(3);
expect(['a', 'b']).toExactlyMatch(r`(?<=\G)a|\Gb`);
expect('a').toExactlyMatch(r`((?<=\G)a)`);
expect(['a', 'A']).toExactlyMatch({
pattern: r`(?i)(?<=\G)a`,
maxTestTarget: maxTestTargetForPatternMods,
});
// Similar but not covered
[ r`(?<=\G|)a`,
r`(?:(?<=\G))?a`,
r`(?<=\G)a|b`,
].forEach(pattern => {
expect(() => toDetails(pattern, {avoidSubclass: true})).toThrow();
});
});

it('should throw if leading in a leading positive lookbehind', () => {
// [Oniguruma] Matches at index 3 within `abc`, but doesn't match within `aabc`
// [TODO] Emulatable by replacing `\G` with `^`, slicing the string to `lastIndex`, and doing
// a non-sticky search
expect(() => toDetails(r`(?<=\Gabc)`)).toThrow();
});

it('should throw if leading in a leading negative lookaround', () => {
expect(() => toDetails(r`(?!\G)a`, {avoidSubclass: true})).toThrow();
expect(() => toDetails(r`(?<!\G)a`, {avoidSubclass: true})).toThrow();
});

// Just documenting current behavior
// Documenting current behavior
it('should throw for redundant but otherwise supportable assertions', () => {
expect(() => toDetails(r`\G\Ga`)).toThrow();
expect(() => toDetails(r`\Ga|\G\Gb`)).toThrow();
Expand Down
22 changes: 1 addition & 21 deletions src/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -705,27 +705,7 @@ function getKids(node) {
}

function getLeadingG(els) {
let firstToConsider = els.find(el => el.type !== AstTypes.Directive);
if (!firstToConsider) {
return null;
}
// Special case for leading positive lookaround with leading `\G`; else all leading assertions
// are ignored when looking for `\G`; can be nested within a wrapper group via subsequent
// recursion into groups
if (
isLookaround(firstToConsider) &&
!firstToConsider.negate &&
firstToConsider.alternatives.length === 1 &&
firstToConsider.alternatives[0].elements.length
) {
const els = firstToConsider.alternatives[0].elements;
const index = firstToConsider.kind === AstAssertionKinds.lookahead ? 0 : els.length - 1;
// `\G` is first in lookahead or last in lookbehind
if (els[index].kind === AstAssertionKinds.search_start) {
return els[index];
}
}
firstToConsider = els.find(el => {
const firstToConsider = els.find(el => {
return el.kind === AstAssertionKinds.search_start ?
true :
( el.type !== AstTypes.Assertion &&
Expand Down

0 comments on commit 1c8c5b6

Please sign in to comment.