Score grammar matches using longest fileType match

Previously the score for two grammars matching on path
was equal and so the first one would be selected.

Now the longer match will have a higher score and will be selected
over other grammars with shorter fileType match lengths.

Closes #602
This commit is contained in:
Kevin Sawicki
2013-06-24 18:23:54 -07:00
parent 6b6ce03c72
commit 86c8343107
2 changed files with 31 additions and 9 deletions

View File

@@ -1,4 +1,5 @@
fsUtils = require 'fs-utils'
TextMateGrammar = require 'text-mate-grammar'
describe "the `syntax` global", ->
beforeEach ->
@@ -57,6 +58,23 @@ describe "the `syntax` global", ->
syntax.clearGrammarOverrideForPath(path)
expect(syntax.selectGrammar(path).name).not.toBe 'Ruby'
describe "when multiple grammars have matching fileTypes", ->
it "selects the grammar with the longest fileType match", ->
grammar1 = new TextMateGrammar
name: 'test1'
scopeName: 'source1'
fileTypes: ['test', 'more.test']
grammar2 = new TextMateGrammar
name: 'test2'
scopeName: 'source2'
fileTypes: ['test']
syntax.addGrammar(grammar1)
syntax.addGrammar(grammar2)
expect(syntax.selectGrammar('more.test', '')).toBe grammar1
describe ".removeGrammar(grammar)", ->
it "removes the grammar, so it won't be returned by selectGrammar", ->
grammar = syntax.selectGrammar('foo.js')

View File

@@ -74,14 +74,13 @@ class TextMateGrammar
getScore: (filePath, contents) ->
contents = fsUtils.read(filePath) if not contents? and fsUtils.isFileSync(filePath)
if syntax.grammarOverrideForPath(filePath) is @scopeName
3
2 + filePath.length
else if @matchesContents(contents)
2
else if @matchesPath(filePath)
1
1 + filePath.length
else
-1
@getPathScore(filePath)
matchesContents: (contents) ->
return false unless contents? and @firstLineRegex?
@@ -100,13 +99,18 @@ class TextMateGrammar
lines = contents.split('\n')
@firstLineRegex.test(lines[0..numberOfNewlinesInRegex].join('\n'))
matchesPath: (filePath) ->
return false unless filePath?
getPathScore: (filePath) ->
return -1 unless filePath?
pathComponents = filePath.split(pathSplitRegex)
_.find @fileTypes, (fileType) ->
pathScore = -1
@fileTypes.forEach (fileType) ->
fileTypeComponents = fileType.split(pathSplitRegex)
pathSuffix = pathComponents[-fileTypeComponents.length..-1]
_.isEqual(pathSuffix, fileTypeComponents)
if _.isEqual(pathSuffix, fileTypeComponents)
pathScore = Math.max(pathScore, fileType.length)
pathScore
tokenizeLine: (line, ruleStack=[@getInitialRule()], firstLine=false) ->
originalRuleStack = ruleStack