Skip to content

Commit

Permalink
Fix a bug in TreeCursor.matchContext
Browse files Browse the repository at this point in the history
FIX: Fix a bug in `TreeCursor.matchContext` where, if the context fell
partially in a buffer node and partially in tree nodes, it could return
incorrect results.

Closes codemirror/dev#1449
  • Loading branch information
marijnh committed Oct 2, 2024
1 parent 854be2c commit 7c3bd8c
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 5 deletions.
10 changes: 5 additions & 5 deletions src/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,7 @@ abstract class BaseNode implements SyntaxNode {
}

matchContext(context: readonly string[]): boolean {
return matchNodeContext(this, context)
return matchNodeContext(this.parent, context)
}

enterUnfinishedNodesBefore(pos: number) {
Expand Down Expand Up @@ -935,8 +935,8 @@ function getChildren(node: SyntaxNode, type: string | number, before: string | n
}
}

function matchNodeContext(node: SyntaxNode, context: readonly string[], i = context.length - 1): boolean {
for (let p: SyntaxNode | null = node.parent; i >= 0; p = p.parent) {
function matchNodeContext(node: SyntaxNode | null, context: readonly string[], i = context.length - 1): boolean {
for (let p = node; i >= 0; p = p.parent) {
if (!p) return false
if (!p.type.isAnonymous) {
if (context[i] && context[i] != p.name) return false
Expand Down Expand Up @@ -1331,10 +1331,10 @@ export class TreeCursor implements SyntaxNodeRef {
/// of direct parent node names. Empty strings in the context array
/// are treated as wildcards.
matchContext(context: readonly string[]): boolean {
if (!this.buffer) return matchNodeContext(this.node, context)
if (!this.buffer) return matchNodeContext(this.node.parent, context)
let {buffer} = this.buffer, {types} = buffer.set
for (let i = context.length - 1, d = this.stack.length - 1; i >= 0; d--) {
if (d < 0) return matchNodeContext(this.node, context, i)
if (d < 0) return matchNodeContext(this._tree, context, i)
let type = types[buffer.buffer[this.stack[d]]]
if (!type.isAnonymous) {
if (context[i] && context[i] != type.name) return false
Expand Down
20 changes: 20 additions & 0 deletions test/test-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,3 +324,23 @@ describe("TreeCursor", () => {
ist(c.type, NodeType.none)
})
})

describe("matchContext", () => {
it("can match on nodes", () => {
ist(simple().resolve(10, 1).matchContext(["T", "Pa", "Br"]))
})

it("can match wildcards", () => {
ist(simple().resolve(10, 1).matchContext(["T", "", "Br"]))
})

it("can mismatch on nodes", () => {
ist(!simple().resolve(10, 1).matchContext(["Q", "Br"]))
})

it("can match on cursor", () => {
let c = simple().cursor()
for (let i = 0; i < 3; i++) c.enter(15, -1)
ist(c.matchContext(["T", "Pa", "Br"]))
})
})

0 comments on commit 7c3bd8c

Please sign in to comment.