Avoid recursive call to moveToSuccessor, which is blowing the stack

This commit is contained in:
Nathan Sobo
2016-01-26 17:42:28 -07:00
parent 47338253db
commit d0e29bfc2c
2 changed files with 53 additions and 18 deletions

View File

@@ -1113,3 +1113,30 @@ describe "TokenizedBuffer", ->
expect(iterator.seek(Point(2, 0))).toEqual(["source.js"])
iterator.moveToSuccessor() # ensure we don't infinitely loop (regression test)
it "does not report columns beyond the length of the line", ->
waitsForPromise ->
atom.packages.activatePackage('language-coffee-script')
runs ->
buffer = new TextBuffer(text: "# hello\n# world")
tokenizedBuffer = new TokenizedBuffer({
buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert
})
tokenizedBuffer.setGrammar(atom.grammars.selectGrammar(".coffee"))
fullyTokenize(tokenizedBuffer)
iterator = tokenizedBuffer.buildIterator()
iterator.seek(Point(0, 0))
iterator.moveToSuccessor()
iterator.moveToSuccessor()
expect(iterator.getPosition().column).toBe(7)
iterator.moveToSuccessor()
expect(iterator.getPosition().column).toBe(0)
iterator.seek(Point(0, 7))
expect(iterator.getPosition().column).toBe(7)
iterator.seek(Point(0, 8))
expect(iterator.getPosition().column).toBe(7)

View File

@@ -14,6 +14,7 @@ class TokenizedBufferIterator
currentLine = @tokenizedBuffer.tokenizedLineForRow(position.row)
containingTags = currentLine.openScopes.map (id) => @grammarRegistry.scopeForId(id)
@currentTags = currentLine.tags
@currentLineLength = currentLine.text.length
currentColumn = 0
for tag, index in @currentTags
if tag >= 0
@@ -32,39 +33,46 @@ class TokenizedBufferIterator
@openTags.push(scopeName)
@tagIndex ?= @currentTags.length
@position = Point(position.row, currentColumn)
@position = Point(position.row, Math.min(@currentLineLength, currentColumn))
containingTags
moveToSuccessor: ->
if @tagIndex is @currentTags.length
@position = Point(@position.row + 1, 0)
@currentTags = @tokenizedBuffer.tokenizedLineForRow(@position.row)?.tags
return false unless @currentTags?
@tagIndex = 0
else
@position = Point(@position.row, @position.column + @currentTags[@tagIndex])
@tagIndex++
@openTags = []
@closeTags = []
loop
tag = @currentTags[@tagIndex]
if tag >= 0 or @tagIndex is @currentTags.length
if @tagIndex is @currentTags.length
if @isAtTagBoundary()
break
else
return @moveToSuccessor()
return false unless @moveToNextLine()
else
scopeName = @grammarRegistry.scopeForId(tag)
if tag % 2 is 0
@closeTags.push(scopeName)
tag = @currentTags[@tagIndex]
if tag >= 0
if @isAtTagBoundary()
break
else
@position = Point(@position.row, Math.min(@currentLineLength, @position.column + @currentTags[@tagIndex]))
else
@openTags.push(scopeName)
@tagIndex++
scopeName = @grammarRegistry.scopeForId(tag)
if tag % 2 is 0
@closeTags.push(scopeName)
else
@openTags.push(scopeName)
@tagIndex++
true
# Private
moveToNextLine: ->
@position = Point(@position.row + 1, 0)
tokenizedLine = @tokenizedBuffer.tokenizedLineForRow(@position.row)
return false unless tokenizedLine?
@currentTags = tokenizedLine.tags
@currentLineLength = tokenizedLine.text.length
@tagIndex = 0
true
getPosition: ->
@position