mirror of
https://github.com/atom/atom.git
synced 2026-01-26 15:28:27 -05:00
Rework handling of edited ranges
This commit is contained in:
@@ -37,7 +37,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await languageMode.reparsePromise
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
|
||||
expectTokensToEqual(editor, [[
|
||||
{text: 'aa.', scopes: ['source']},
|
||||
@@ -67,7 +67,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await languageMode.reparsePromise
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
|
||||
expectTokensToEqual(editor, [[
|
||||
{text: 'a', scopes: ['source', 'variable']},
|
||||
@@ -94,7 +94,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await languageMode.reparsePromise
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
|
||||
expectTokensToEqual(editor, [
|
||||
[
|
||||
@@ -122,9 +122,8 @@ describe('TreeSitterLanguageMode', () => {
|
||||
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await languageMode.reparsePromise
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
|
||||
editor.screenLineForScreenRow(0)
|
||||
expect(
|
||||
languageMode.tree.rootNode.descendantForPosition(Point(1, 2), Point(1, 6)).toString()
|
||||
).toBe('(declaration (primitive_type) (identifier) (MISSING))')
|
||||
@@ -168,7 +167,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await languageMode.reparsePromise
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
|
||||
// missing closing paren
|
||||
expectTokensToEqual(editor, [
|
||||
@@ -179,7 +178,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
])
|
||||
|
||||
buffer.append(')')
|
||||
await languageMode.reparsePromise
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
expectTokensToEqual(editor, [
|
||||
[
|
||||
{text: 'a', scopes: ['function']},
|
||||
@@ -209,8 +208,8 @@ describe('TreeSitterLanguageMode', () => {
|
||||
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await languageMode.reparsePromise
|
||||
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
expectTokensToEqual(editor, [
|
||||
[{text: '// abc', scopes: ['comment']}],
|
||||
[{text: '', scopes: []}],
|
||||
@@ -223,7 +222,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
])
|
||||
|
||||
buffer.insert([2, 0], ' ')
|
||||
await languageMode.reparsePromise
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
expectTokensToEqual(editor, [
|
||||
[{text: '// abc', scopes: ['comment']}],
|
||||
[{text: '', scopes: []}],
|
||||
@@ -248,9 +247,10 @@ describe('TreeSitterLanguageMode', () => {
|
||||
});
|
||||
|
||||
buffer.setText('`\na${1}\nb${2}\n`;')
|
||||
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await languageMode.reparsePromise
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
|
||||
expectTokensToEqual(editor, [
|
||||
[
|
||||
@@ -288,7 +288,8 @@ describe('TreeSitterLanguageMode', () => {
|
||||
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await languageMode.reparsePromise
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
await new Promise(process.nextTick)
|
||||
|
||||
expectTokensToEqual(editor, [
|
||||
[
|
||||
@@ -314,8 +315,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
],
|
||||
])
|
||||
|
||||
await languageMode.reparsePromise
|
||||
expect(languageMode.reparsePromise).not.toBeNull()
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
expectTokensToEqual(editor, [
|
||||
[
|
||||
{text: 'new ', scopes: []},
|
||||
@@ -324,8 +324,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
],
|
||||
])
|
||||
|
||||
await languageMode.reparsePromise
|
||||
expect(languageMode.reparsePromise).toBeNull()
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
expectTokensToEqual(editor, [
|
||||
[
|
||||
{text: 'new ', scopes: []},
|
||||
@@ -378,7 +377,8 @@ describe('TreeSitterLanguageMode', () => {
|
||||
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar: jsGrammar, grammars: atom.grammars})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await languageMode.reparsePromise
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
|
||||
expectTokensToEqual(editor, [
|
||||
[
|
||||
@@ -407,7 +407,8 @@ describe('TreeSitterLanguageMode', () => {
|
||||
|
||||
const range = buffer.findSync('html')
|
||||
buffer.setTextInRange(range, 'xml')
|
||||
await languageMode.reparsePromise
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
|
||||
expectTokensToEqual(editor, [
|
||||
[
|
||||
@@ -437,7 +438,8 @@ describe('TreeSitterLanguageMode', () => {
|
||||
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar: htmlGrammar, grammars: atom.grammars})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await languageMode.reparsePromise
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
|
||||
expectTokensToEqual(editor, [
|
||||
[
|
||||
@@ -473,8 +475,9 @@ describe('TreeSitterLanguageMode', () => {
|
||||
buffer.setText('node.innerHTML = html `\na ${b}<img src="d">\n`;')
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar: jsGrammar, grammars: atom.grammars})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await languageMode.reparsePromise
|
||||
expectTokensToEqual(editor, [
|
||||
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
expectTokensToEqual(editor, [
|
||||
[
|
||||
{text: 'node.', scopes: []},
|
||||
{text: 'innerHTML', scopes: ['property']},
|
||||
@@ -495,7 +498,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
])
|
||||
|
||||
atom.grammars.addGrammar(htmlGrammar)
|
||||
await languageMode.reparsePromise
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
expectTokensToEqual(editor, [
|
||||
[
|
||||
{text: 'node.', scopes: []},
|
||||
@@ -626,9 +629,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await languageMode.reparsePromise
|
||||
|
||||
editor.screenLineForScreenRow(0)
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
|
||||
expect(editor.isFoldableAtBufferRow(0)).toBe(false)
|
||||
expect(editor.isFoldableAtBufferRow(1)).toBe(true)
|
||||
@@ -690,9 +691,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await languageMode.reparsePromise
|
||||
|
||||
editor.screenLineForScreenRow(0)
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
|
||||
expect(editor.isFoldableAtBufferRow(0)).toBe(true)
|
||||
expect(editor.isFoldableAtBufferRow(1)).toBe(false)
|
||||
@@ -741,9 +740,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await languageMode.reparsePromise
|
||||
|
||||
editor.screenLineForScreenRow(0)
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
|
||||
expect(editor.isFoldableAtBufferRow(0)).toBe(true)
|
||||
expect(editor.isFoldableAtBufferRow(1)).toBe(false)
|
||||
@@ -818,9 +815,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await languageMode.reparsePromise
|
||||
|
||||
editor.screenLineForScreenRow(0)
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
|
||||
editor.foldBufferRow(3)
|
||||
expect(getDisplayText(editor)).toBe(dedent `
|
||||
@@ -902,7 +897,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
|
||||
const languageMode = new TreeSitterLanguageMode({buffer, grammar})
|
||||
buffer.setLanguageMode(languageMode)
|
||||
await languageMode.reparsePromise
|
||||
await nextHighlightingUpdate(languageMode)
|
||||
|
||||
// Void elements have only one child
|
||||
expect(editor.isFoldableAtBufferRow(1)).toBe(false)
|
||||
@@ -938,9 +933,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
`)
|
||||
|
||||
buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar}))
|
||||
await buffer.getLanguageMode().reparsePromise
|
||||
|
||||
editor.screenLineForScreenRow(0)
|
||||
await nextHighlightingUpdate(buffer.getLanguageMode())
|
||||
|
||||
editor.foldBufferRow(0)
|
||||
expect(getDisplayText(editor)).toBe(dedent `
|
||||
@@ -1040,9 +1033,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
buffer.setText('foo({bar: baz});')
|
||||
|
||||
buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar}))
|
||||
await buffer.getLanguageMode().reparsePromise
|
||||
|
||||
editor.screenLineForScreenRow(0)
|
||||
await nextHighlightingUpdate(buffer.getLanguageMode())
|
||||
expect(editor.scopeDescriptorForBufferPosition([0, 6]).getScopesArray()).toEqual([
|
||||
'javascript',
|
||||
'program',
|
||||
@@ -1071,9 +1062,7 @@ describe('TreeSitterLanguageMode', () => {
|
||||
`)
|
||||
|
||||
buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar}))
|
||||
await buffer.getLanguageMode().reparsePromise
|
||||
|
||||
editor.screenLineForScreenRow(0)
|
||||
await nextHighlightingUpdate(buffer.getLanguageMode())
|
||||
|
||||
editor.setCursorBufferPosition([1, 3])
|
||||
editor.selectLargerSyntaxNode()
|
||||
|
||||
@@ -113,10 +113,6 @@ class TreeSitterLanguageMode {
|
||||
return this.rootLanguageLayer.tree
|
||||
}
|
||||
|
||||
get reparsePromise () {
|
||||
return this.rootLanguageLayer.currentParsePromise
|
||||
}
|
||||
|
||||
updateForInjection (grammar) {
|
||||
this.rootLanguageLayer.updateInjections(grammar)
|
||||
}
|
||||
@@ -474,12 +470,22 @@ class LanguageLayer {
|
||||
this.tree.edit(this._treeEditForBufferChange(
|
||||
oldRange.start, oldRange.end, newRange.end, oldText, newText
|
||||
))
|
||||
|
||||
if (this.editedRange) {
|
||||
if (newRange.start.isLessThan(this.editedRange.start)) {
|
||||
this.editedRange.start = newRange.start
|
||||
}
|
||||
if (oldRange.end.isLessThan(this.editedRange.end)) {
|
||||
this.editedRange.end = newRange.end.traverse(this.editedRange.end.traversalFrom(oldRange.end))
|
||||
} else {
|
||||
this.editedRange.end = newRange.end
|
||||
}
|
||||
} else {
|
||||
this.editedRange = newRange.copy()
|
||||
}
|
||||
}
|
||||
|
||||
if (this.currentParsePromise) {
|
||||
if (!this.patchSinceCurrentParseStarted) {
|
||||
this.patchSinceCurrentParseStarted = new Patch()
|
||||
}
|
||||
if (this.patchSinceCurrentParseStarted) {
|
||||
this.patchSinceCurrentParseStarted.splice(
|
||||
oldRange.start,
|
||||
oldRange.end,
|
||||
@@ -500,22 +506,12 @@ class LanguageLayer {
|
||||
}
|
||||
|
||||
async update (nodeRangeSet) {
|
||||
if (this.currentParsePromise) return this.currentParsePromise
|
||||
|
||||
this.currentParsePromise = this._performUpdate(nodeRangeSet)
|
||||
await this.currentParsePromise
|
||||
this.currentParsePromise = null
|
||||
|
||||
if (this.patchSinceCurrentParseStarted) {
|
||||
const changes = this.patchSinceCurrentParseStarted.getChanges()
|
||||
for (let i = changes.length - 1; i >= 0; i--) {
|
||||
const {oldStart, oldEnd, newEnd, oldText, newText} = changes[i]
|
||||
this.tree.edit(this._treeEditForBufferChange(
|
||||
oldStart, oldEnd, newEnd, oldText, newText
|
||||
))
|
||||
}
|
||||
this.patchSinceCurrentParseStarted = null
|
||||
this.update(nodeRangeSet)
|
||||
if (!this.currentParsePromise) {
|
||||
do {
|
||||
this.currentParsePromise = this._performUpdate(nodeRangeSet)
|
||||
await this.currentParsePromise
|
||||
} while (this.tree && this.tree.rootNode.hasChanges())
|
||||
this.currentParsePromise = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,6 +532,10 @@ class LanguageLayer {
|
||||
if (includedRanges.length === 0) return
|
||||
}
|
||||
|
||||
let affectedRange = this.editedRange
|
||||
this.editedRange = null
|
||||
|
||||
this.patchSinceCurrentParseStarted = new Patch()
|
||||
const tree = await this.languageMode.parse(
|
||||
this.grammar.languageModule,
|
||||
this.tree,
|
||||
@@ -543,14 +543,20 @@ class LanguageLayer {
|
||||
)
|
||||
tree.buffer = this.languageMode.buffer
|
||||
|
||||
let affectedRange
|
||||
if (this.tree) {
|
||||
const editedRange = this.tree.getEditedRange()
|
||||
if (!editedRange) return
|
||||
affectedRange = rangeForNode(editedRange)
|
||||
const changes = this.patchSinceCurrentParseStarted.getChanges()
|
||||
this.patchSinceCurrentParseStarted = null
|
||||
for (let i = changes.length - 1; i >= 0; i--) {
|
||||
const {oldStart, oldEnd, newEnd, oldText, newText} = changes[i]
|
||||
tree.edit(this._treeEditForBufferChange(
|
||||
oldStart, oldEnd, newEnd, oldText, newText
|
||||
))
|
||||
}
|
||||
|
||||
if (this.tree) {
|
||||
const rangesWithSyntaxChanges = this.tree.getChangedRanges(tree)
|
||||
this.tree = tree
|
||||
|
||||
if (!affectedRange) return
|
||||
if (rangesWithSyntaxChanges.length > 0) {
|
||||
for (const range of rangesWithSyntaxChanges) {
|
||||
this.languageMode.emitRangeUpdate(rangeForNode(range))
|
||||
@@ -560,6 +566,8 @@ class LanguageLayer {
|
||||
rangesWithSyntaxChanges[0].startPosition,
|
||||
last(rangesWithSyntaxChanges).endPosition
|
||||
))
|
||||
} else {
|
||||
this.languageMode.emitRangeUpdate(affectedRange)
|
||||
}
|
||||
} else {
|
||||
this.tree = tree
|
||||
|
||||
Reference in New Issue
Block a user