mirror of
https://github.com/atom/atom.git
synced 2026-01-23 05:48:10 -05:00
Stop tokenizing line when the same rule is pushed more than once
Previously Rails classes would infinitly loop if the Ruby on Rails grammar was loaded but the Ruby grammar had not been. This occurred because a rule was continually pushing itself on the stack but never advancing. Now if the position does not advance and the last two rules in the stack have the same scope the last rule is popped and the entire line is tokenized with the current scopes. Closes #524 #486
This commit is contained in:
@@ -488,6 +488,29 @@ describe "TextMateGrammar", ->
|
||||
expect(tokens[2].value).toBe "SELECT"
|
||||
expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "keyword.other.DML.sql"]
|
||||
|
||||
describe "when the position doesn't advance and rule includes $self and matches itself", ->
|
||||
it "token the entire line using the rule", ->
|
||||
grammar = new TextMateGrammar
|
||||
name: "test"
|
||||
scopeName: "source"
|
||||
repository: {}
|
||||
patterns: [
|
||||
{
|
||||
name: "text"
|
||||
begin: "(?=forever)"
|
||||
end: "whatevs"
|
||||
patterns: [
|
||||
include: "$self"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
{tokens} = grammar.tokenizeLine("forever and ever")
|
||||
|
||||
expect(tokens.length).toBe 1
|
||||
expect(tokens[0].value).toBe "forever and ever"
|
||||
expect(tokens[0].scopes).toEqual ["source", "text"]
|
||||
|
||||
describe "language-specific integration tests", ->
|
||||
lines = null
|
||||
|
||||
|
||||
@@ -155,9 +155,19 @@ 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()
|
||||
if position == previousPosition
|
||||
if ruleStack.length == previousRuleStackLength
|
||||
console.error("Popping rule because it loops at column #{position} of line '#{line}'", _.clone(ruleStack))
|
||||
ruleStack.pop()
|
||||
|
||||
[penultimateRule, lastRule] = ruleStack[-2..]
|
||||
if lastRule? and penultimateRule.scopeName == lastRule.scopeName
|
||||
ruleStack.pop()
|
||||
tokens.push(new Token(
|
||||
value: line[position...line.length]
|
||||
scopes: scopes
|
||||
))
|
||||
break
|
||||
|
||||
ruleStack.forEach (rule) -> rule.clearAnchorPosition()
|
||||
{ tokens, ruleStack }
|
||||
|
||||
Reference in New Issue
Block a user