diff --git a/spec/app/text-mate-grammar-spec.coffee b/spec/app/text-mate-grammar-spec.coffee index 045edf9cb..369f10e7d 100644 --- a/spec/app/text-mate-grammar-spec.coffee +++ b/spec/app/text-mate-grammar-spec.coffee @@ -309,7 +309,7 @@ describe "TextMateGrammar", -> expect(tokens[4].value).toBe "three(four(five(_param_)))))" expect(ruleStack).toEqual originalRuleStack - describe "when a grammar's captures has patterns", -> + describe "when a grammar has a capture with patterns", -> beforeEach -> atom.activatePackage('php.tmbundle', sync: true) @@ -331,3 +331,29 @@ describe "TextMateGrammar", -> expect(tokens[6].value).toBe "function" expect(tokens[6].scopes).toEqual ["text.html.php", "meta.embedded.line.php", "source.php", "meta.function.php", "storage.type.function.php"] + + it "ignores child captures of a capture with patterns", -> + grammar = new TextMateGrammar + name: "test" + scopeName: "source" + repository: {} + patterns: [ + { + name: "text" + match: "(a(b))" + captures: + "1": + patterns: [ + { + match: "ab" + name: "a" + } + ] + "2": + name: "b" + } + ] + {tokens} = grammar.tokenizeLine("ab") + + expect(tokens[0].value).toBe "ab" + expect(tokens[0].scopes).toEqual ["source", "text", "a"] diff --git a/src/app/text-mate-grammar.coffee b/src/app/text-mate-grammar.coffee index a3601a1e2..039df3243 100644 --- a/src/app/text-mate-grammar.coffee +++ b/src/app/text-mate-grammar.coffee @@ -397,11 +397,9 @@ class Pattern tokens getTokensForCaptureRule: (rule, line, captureStart, captureEnd, scopes, stack) -> - line = line.substring(captureStart, captureEnd) - {tokens} = rule.grammar.tokenizeLine(line, [stack..., rule]) - matchLength = 0 - matchLength += token.value.length for token in tokens - {captureTokens: tokens, matchEndPosition: captureStart + matchLength} + captureText = line.substring(captureStart, captureEnd) + {tokens} = rule.grammar.tokenizeLine(captureText, [stack..., rule]) + tokens getTokensForCaptureIndices: (line, captureIndices, scopes, stack) -> [parentCaptureIndex, parentCaptureStart, parentCaptureEnd] = shiftCapture(captureIndices) @@ -411,36 +409,38 @@ class Pattern scopes = scopes.concat(scope) if captureRule = @captures[parentCaptureIndex]?.rule - {captureTokens, matchEndPosition} = @getTokensForCaptureRule(captureRule, line, parentCaptureStart, parentCaptureEnd, scopes, stack) + captureTokens = @getTokensForCaptureRule(captureRule, line, parentCaptureStart, parentCaptureEnd, scopes, stack) tokens.push(captureTokens...) - parentCaptureStart = matchEndPosition - - previousChildCaptureEnd = parentCaptureStart - while captureIndices.length and captureIndices[1] < parentCaptureEnd - [childCaptureIndex, childCaptureStart, childCaptureEnd] = captureIndices - - emptyCapture = childCaptureEnd - childCaptureStart == 0 - captureHasNoScope = not @captures[childCaptureIndex] - if emptyCapture or captureHasNoScope + # Consume child captures + while captureIndices.length and captureIndices[1] < parentCaptureEnd shiftCapture(captureIndices) - continue + else + previousChildCaptureEnd = parentCaptureStart + while captureIndices.length and captureIndices[1] < parentCaptureEnd + [childCaptureIndex, childCaptureStart, childCaptureEnd] = captureIndices - if childCaptureStart > previousChildCaptureEnd + emptyCapture = childCaptureEnd - childCaptureStart == 0 + captureHasNoScope = not @captures[childCaptureIndex] + if emptyCapture or captureHasNoScope + shiftCapture(captureIndices) + continue + + if childCaptureStart > previousChildCaptureEnd + tokens.push(new Token( + value: line[previousChildCaptureEnd...childCaptureStart] + scopes: scopes + )) + + captureTokens = @getTokensForCaptureIndices(line, captureIndices, scopes, stack) + tokens.push(captureTokens...) + previousChildCaptureEnd = childCaptureEnd + + if parentCaptureEnd > previousChildCaptureEnd tokens.push(new Token( - value: line[previousChildCaptureEnd...childCaptureStart] + value: line[previousChildCaptureEnd...parentCaptureEnd] scopes: scopes )) - captureTokens = @getTokensForCaptureIndices(line, captureIndices, scopes, stack) - tokens.push(captureTokens...) - previousChildCaptureEnd = childCaptureEnd - - if parentCaptureEnd > previousChildCaptureEnd - tokens.push(new Token( - value: line[previousChildCaptureEnd...parentCaptureEnd] - scopes: scopes - )) - tokens ###