mirror of
https://github.com/atom/atom.git
synced 2026-01-23 05:48:10 -05:00
Update .foldable on tokenized lines based on indentation
This commit is contained in:
@@ -118,7 +118,8 @@ describe "TokenizedBuffer", ->
|
||||
expect(tokenizedBuffer.firstInvalidRow()).toBe 3
|
||||
|
||||
advanceClock()
|
||||
expect(changeHandler).toHaveBeenCalledWith(start: 3, end: 7, delta: 0)
|
||||
# we discover that row 2 starts a foldable region when line 3 gets tokenized
|
||||
expect(changeHandler).toHaveBeenCalledWith(start: 2, end: 7, delta: 0)
|
||||
expect(tokenizedBuffer.firstInvalidRow()).toBe 8
|
||||
|
||||
describe "when there is a buffer change surrounding an invalid row", ->
|
||||
@@ -168,7 +169,7 @@ describe "TokenizedBuffer", ->
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
delete event.bufferChange
|
||||
expect(event).toEqual(start: 2, end: 2, delta: 0)
|
||||
expect(event).toEqual(start: 1, end: 2, delta: 0)
|
||||
changeHandler.reset()
|
||||
|
||||
advanceClock()
|
||||
@@ -178,7 +179,8 @@ describe "TokenizedBuffer", ->
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
delete event.bufferChange
|
||||
expect(event).toEqual(start: 3, end: 5, delta: 0)
|
||||
# we discover that row 2 starts a foldable region when line 3 gets tokenized
|
||||
expect(event).toEqual(start: 2, end: 5, delta: 0)
|
||||
|
||||
it "resumes highlighting with the state of the previous line", ->
|
||||
buffer.insert([0, 0], '/*')
|
||||
@@ -206,7 +208,7 @@ describe "TokenizedBuffer", ->
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
delete event.bufferChange
|
||||
expect(event).toEqual(start: 1, end: 3, delta: -2)
|
||||
expect(event).toEqual(start: 0, end: 3, delta: -2) # starts at 0 because foldable on row 0 becomes false
|
||||
|
||||
describe "when the change invalidates the tokenization of subsequent lines", ->
|
||||
it "schedules the invalidated lines to be tokenized in the background", ->
|
||||
@@ -219,7 +221,7 @@ describe "TokenizedBuffer", ->
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
delete event.bufferChange
|
||||
expect(event).toEqual(start: 2, end: 3, delta: -1)
|
||||
expect(event).toEqual(start: 1, end: 3, delta: -1)
|
||||
changeHandler.reset()
|
||||
|
||||
advanceClock()
|
||||
@@ -228,7 +230,8 @@ describe "TokenizedBuffer", ->
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
delete event.bufferChange
|
||||
expect(event).toEqual(start: 3, end: 4, delta: 0)
|
||||
# we discover that row 2 starts a foldable region when line 3 gets tokenized
|
||||
expect(event).toEqual(start: 2, end: 4, delta: 0)
|
||||
|
||||
describe "when lines are both updated and inserted", ->
|
||||
it "updates tokens to reflect the change", ->
|
||||
@@ -252,7 +255,7 @@ describe "TokenizedBuffer", ->
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
delete event.bufferChange
|
||||
expect(event).toEqual(start: 1, end: 2, delta: 2)
|
||||
expect(event).toEqual(start: 0, end: 2, delta: 2) # starts at 0 because .foldable becomes false on row 0
|
||||
|
||||
describe "when the change invalidates the tokenization of subsequent lines", ->
|
||||
it "schedules the invalidated lines to be tokenized in the background", ->
|
||||
@@ -263,7 +266,7 @@ describe "TokenizedBuffer", ->
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
delete event.bufferChange
|
||||
expect(event).toEqual(start: 2, end: 2, delta: 2)
|
||||
expect(event).toEqual(start: 1, end: 2, delta: 2)
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0].scopes).toEqual ['source.js', 'comment.block.js', 'punctuation.definition.comment.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
|
||||
@@ -776,7 +779,7 @@ describe "TokenizedBuffer", ->
|
||||
buffer.setTextInRange([[7, 0], [8, 65]], ' ok')
|
||||
|
||||
delete changeHandler.argsForCall[0][0].bufferChange
|
||||
expect(changeHandler).toHaveBeenCalledWith(start: 5, end: 10, delta: -1)
|
||||
expect(changeHandler).toHaveBeenCalledWith(start: 4, end: 10, delta: -1) # starts at row 4 because it became foldable
|
||||
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(5).indentLevel).toBe 2
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(6).indentLevel).toBe 2
|
||||
@@ -803,7 +806,7 @@ describe "TokenizedBuffer", ->
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).foldable).toBe true
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).foldable).toBe false
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).foldable).toBe false
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).foldable).toBe false
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).foldable).toBe true # because of indent
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(13).foldable).toBe true
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(14).foldable).toBe false
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(15).foldable).toBe false
|
||||
@@ -818,9 +821,48 @@ describe "TokenizedBuffer", ->
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).foldable).toBe false
|
||||
|
||||
changes = []
|
||||
buffer.delete([[0, Infinity], [1, 0]])
|
||||
buffer.undo()
|
||||
expect(changes).toEqual [{start: 0, end: 2, delta: -1}]
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).foldable).toBe true
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).foldable).toBe false
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).foldable).toBe false
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).foldable).toBe false
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).foldable).toBe true # because of indent
|
||||
|
||||
it "sets .foldable to true on non-comment lines that precede an increase in indentation", ->
|
||||
buffer.insert([2, 0], ' ') # commented lines preceding an indent aren't foldable
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).foldable).toBe false
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).foldable).toBe false
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).foldable).toBe true
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(4).foldable).toBe true
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(5).foldable).toBe false
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(6).foldable).toBe false
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(7).foldable).toBe true
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(8).foldable).toBe false
|
||||
|
||||
changes = []
|
||||
buffer.insert([7, 0], ' ')
|
||||
expect(changes).toEqual [{start: 6, end: 7, delta: 0}]
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(6).foldable).toBe true
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(7).foldable).toBe false
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(8).foldable).toBe false
|
||||
|
||||
changes = []
|
||||
buffer.undo()
|
||||
expect(changes).toEqual [{start: 6, end: 7, delta: 0}]
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(6).foldable).toBe false
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(7).foldable).toBe true
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(8).foldable).toBe false
|
||||
|
||||
changes = []
|
||||
buffer.insert([7, 0], " \n x\n")
|
||||
expect(changes).toEqual [{start: 6, end: 7, delta: 2}]
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(6).foldable).toBe true
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(7).foldable).toBe false
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(8).foldable).toBe false
|
||||
|
||||
changes = []
|
||||
buffer.insert([9, 0], " ")
|
||||
expect(changes).toEqual [{start: 9, end: 9, delta: 0}]
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(6).foldable).toBe true
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(7).foldable).toBe false
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(8).foldable).toBe false
|
||||
|
||||
@@ -168,7 +168,7 @@ class TokenizedBuffer extends Model
|
||||
@validateRow(endRow)
|
||||
@invalidateRow(endRow + 1) unless filledRegion
|
||||
|
||||
@updateFoldableStatus(startRow, endRow)
|
||||
[startRow, endRow] = @updateFoldableStatus(startRow, endRow)
|
||||
|
||||
event = {start: startRow, end: endRow, delta: 0}
|
||||
@emit 'changed', event
|
||||
@@ -238,27 +238,41 @@ class TokenizedBuffer extends Model
|
||||
row - increment
|
||||
|
||||
updateFoldableStatus: (startRow, endRow) ->
|
||||
scanStartRow = @buffer.previousNonBlankRow(startRow) ? startRow
|
||||
scanStartRow-- while scanStartRow > 0 and @tokenizedLineForRow(scanStartRow).isComment()
|
||||
scanEndRow = @buffer.nextNonBlankRow(endRow) ? endRow
|
||||
scanEndRow++ if scanEndRow < @buffer.getLastRow()
|
||||
scanStartRow = startRow
|
||||
while scanStartRow > 0 and @tokenizedLineForRow(scanStartRow).isComment()
|
||||
scanStartRow = @buffer.previousNonBlankRow(scanStartRow) ? 0
|
||||
|
||||
commentLineCount = 0
|
||||
for row in [scanStartRow..scanEndRow] by 1
|
||||
if @tokenizedLineForRow(row).isComment()
|
||||
if row > 0
|
||||
foldable = commentLineCount is 1
|
||||
unless @tokenizedLineForRow(row - 1).foldable is foldable
|
||||
@tokenizedLineForRow(row - 1).foldable = foldable
|
||||
startRow = Math.min(startRow, row - 1)
|
||||
endRow = Math.max(endRow, row - 1)
|
||||
commentLineCount++
|
||||
else
|
||||
commentLineCount = 0
|
||||
foldable = @isFoldableAtRow(row)
|
||||
line = @tokenizedLineForRow(row)
|
||||
unless line.foldable is foldable
|
||||
line.foldable = foldable
|
||||
startRow = Math.min(startRow, row)
|
||||
endRow = Math.max(endRow, row)
|
||||
|
||||
[startRow, endRow]
|
||||
|
||||
isFoldableAtRow: (row) ->
|
||||
@isFoldableCodeAtRow(row) or @isFoldableCommentAtRow(row)
|
||||
|
||||
# Returns a {Boolean} indicating whether the given buffer row starts
|
||||
# a a foldable row range due to the code's indentation patterns.
|
||||
isFoldableCodeAtRow: (row) ->
|
||||
return false if @buffer.isRowBlank(row) or @tokenizedLineForRow(row).isComment()
|
||||
nextRow = @buffer.nextNonBlankRow(row)
|
||||
return false unless nextRow?
|
||||
|
||||
@indentLevelForRow(nextRow) > @indentLevelForRow(row)
|
||||
|
||||
isFoldableCommentAtRow: (row) ->
|
||||
previousRow = row - 1
|
||||
nextRow = row + 1
|
||||
return false if nextRow > @buffer.getLastRow()
|
||||
|
||||
(row is 0 or not @tokenizedLineForRow(previousRow).isComment()) and
|
||||
@tokenizedLineForRow(row).isComment() and
|
||||
@tokenizedLineForRow(nextRow).isComment()
|
||||
|
||||
buildTokenizedLinesForRows: (startRow, endRow, startingStack) ->
|
||||
ruleStack = startingStack
|
||||
stopTokenizingAt = startRow + @chunkSize
|
||||
|
||||
Reference in New Issue
Block a user