Pop grammar rules that result in infinite loops

This commit is contained in:
Corey Johnson & Nathan Sobo 2013-03-22 10:38:48 -07:00
parent 266c305ebb
commit 84fe0a384d
3 changed files with 34 additions and 1 deletions

View File

@ -258,3 +258,13 @@ describe "TextMateGrammar", ->
{tokens, ruleStack} = grammar.tokenizeLine("if(1){if(1){m()}}")
expect(tokens[5]).toEqual value: "if", scopes: ["source.c", "meta.block.c", "keyword.control.c"]
expect(tokens[10]).toEqual value: "m", scopes: ["source.c", "meta.block.c", "meta.block.c", "meta.function-call.c", "support.function.any-method.c"]
describe "when the grammar can infinitely loop over a line", ->
it "aborts tokenization", ->
spyOn(console, 'error')
window.loadPackage("package-with-infinite-loop-grammar")
grammar = syntax.grammarForFilePath("something.package-with-infinite-loop-grammar")
{tokens} = grammar.tokenizeLine("abc")
expect(tokens[0].value).toBe "a"
expect(tokens[1].value).toBe "bc"
expect(console.error).toHaveBeenCalled()

View File

@ -0,0 +1,18 @@
'fileTypes': ['package-with-infinite-loop-grammar']
'name': 'package-with-infinite-loop-grammar'
'scopeName': 'source.package-with-infinite-loop-grammar'
# This grammar should loop forever if the line contains an `a`
'patterns': [
{
'name': 'start'
'begin': '^'
'end': '$'
'patterns': [
{
name: 'negative-look-ahead'
match: "(?!a)"
}
]
}
]

View File

@ -31,9 +31,10 @@ class TextMateGrammar
ruleStack = new Array(ruleStack...) # clone ruleStack
tokens = []
position = 0
loop
scopes = scopesFromStack(ruleStack)
previousRuleStackLength = ruleStack.length
previousPosition = position
if line.length == 0
tokens = [new Token(value: "", scopes: scopes)]
@ -61,6 +62,10 @@ class TextMateGrammar
))
break
if position == previousPosition and ruleStack.length == previousRuleStackLength
console.error("Popping rule because it loops at column #{position} of line '#{line}'", _.clone(ruleStack))
ruleStack.pop()
ruleStack.forEach (rule) -> rule.clearAnchorPosition()
{ tokens, ruleStack }